在javascript中我们经常使用IIFE。像
这样的东西(function() {
...do stuff to avoid dirtying scope.
}());
Swift中有闭包,函数是第一类对象。我的问题是:Swift中是否有相同的IIFE?
答案 0 :(得分:8)
这里接受的答案是误导性的 - 在这里创建一个立即调用的闭包表达式(IICE)是一种更简单,更优雅的方式。
有关语法的所有细节和差异,请参阅Apple Swift Documentation for closures。有关简单演示,请参阅:
let dateString: NSString = { date in
let timestampFormatter = NSDateFormatter()
timestampFormatter.dateStyle = .MediumStyle
timestampFormatter.timeStyle = .MediumStyle
return timestampFormatter.stringFromDate(date)
}(NSDate())
答案 1 :(得分:3)
使用闭包可以达到类似的效果,当然:
func iife( f : () -> () ) {
f()
}
然后说
iffe {
// my code here
}
如果你真正需要的只是一个范围,而Swift不支持使用{..}作为“范围操作符”,你可以随时
if 1 == 1 {
// oh, look, a scope :-)
}
作为一种不那么花哨的方式来达到同样的效果。 如果您尝试使用RAII模式,则需要依靠ARC来清理,或者使用闭包
if true {
// should also work instead of if 1 == 1
}
答案 2 :(得分:3)
这是一个Swift立即调用的闭包表达式(IICE)的另一个例子 - 我发音为“Icky”(向JavaScript的IIFE点头,发音为“Iffy” - http://benalman.com/news/2010/11/immediately-invoked-function-expression/)
var player:AVAudioPlayer = {
let path = Bundle.main.path(forResource: "sound1", ofType: "mp3")!
let url = NSURL(fileURLWithPath: path)
let p = try! AVAudioPlayer(contentsOf: url as URL)
p.volume = 0.3
p.prepareToPlay()
return p
}()
如果您使用lazy
修饰符,则可以访问self
。
从Swift语言指南:“当属性的初始值依赖于外部因素时,延迟属性非常有用,这些外部因素的值在实例初始化完成之后才知道。当初始值为a时,延迟属性也很有用。属性需要复杂或计算上昂贵的设置,除非或直到需要,否则不应执行。“
let startVolume:Float = 0.3
lazy var player:AVAudioPlayer = {
let path = Bundle.main.path(forResource: "sound1", ofType: "mp3")!
let url = NSURL(fileURLWithPath: path)
let p = try! AVAudioPlayer(contentsOf: url as URL)
p.volume = self.startVolume
p.prepareToPlay()
return p
}()
另请参阅Swift语言指南中的“使用闭包或函数设置默认属性值”。
答案 3 :(得分:0)
当我想要一次性执行代码来初始化属性时,我已经找到了在swift中立即调用的闭包的用法。例如:
myClass {
//One time initialization of managedObjectContext property
lazy var managedObjectContext: NSManagedObjectContext = { () -> NSManagedObjectContext in
let context = NSManagedObjectContext()
//do all the initial setup, etc...
return context
}()
//more stuff...
}
还有其他方法可以实现同样的目标,但我发现这是一个很好的模式。
答案 4 :(得分:0)
您可以使用内置result
而不使用do {}
catch
答案 5 :(得分:0)
这个怎么样?
import pygame, sys
import random
import time
pygame.init()
clock = pygame.time.Clock()
time0 = time.time()
has_passed = False
screen_width = 600
screen_height = 800
enemyWidth = 30
enemyHeight = 10
bg_color = (94, 50, 50)
enemy_color = (0, 0, 0)
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Space Race Game")
class ROCKET:
def __init__(self):
self.rocketImg = pygame.image.load("spaceship.png")
self.rocket_x = screen_width/2 - 32
self.rocket_y = screen_height/2 + 150
def draw_rocket(self):
screen.blit(self.rocketImg, (self.rocket_x, self.rocket_y))
def move_rocket(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and self.rocket_x + 15 > 0:
self.rocket_x -= 5
if key[pygame.K_RIGHT] and self.rocket_x < screen_width - 40:
self.rocket_x += 5
class BULLET(ROCKET):
def __init__(self):
super().__init__()
self.bullet_width = 10
self.bullet_height = 20
self.bullet_x = self.rocket_x + 25
self.bullet_y = self.rocket_y
self.move = [0, 0]
self.bullet_speed = 7
self.bullet_rect = pygame.Rect(self.bullet_x, self.bullet_y, self.bullet_width, self.bullet_height)
def draw_bullet(self, rocket, bullet):
key = pygame.key.get_pressed()
if key[pygame.K_SPACE] and self.move[1] == 0:
self.bullet_x = rocket.rocket_x + 25
self.move[1] = -1
self.bullet_y += self.move[1] * self.bullet_speed
self.bullet_rect.topleft = (self.bullet_x, self.bullet_y)
if self.bullet_y < self.rocket_y - 10:
pygame.draw.rect(screen, (0, 0, 0), self.bullet_rect)
if self.bullet_y < - 20:
self.bullet_y = self.rocket_y
self.move[1] = 0
class ENEMY(ROCKET):
def __init__(self):
super().__init__()
self.enemy_width = enemyWidth
self.enemy_height = enemyHeight
self.enemy_x = random.randint(self.enemy_width, screen_width - self.enemy_width)
self.enemy_y = 0
self.enemy_speed = 1
self.enemy_rect = pygame.Rect(self.enemy_x, self.enemy_y, self.enemy_width, self.enemy_height)
def draw_enemy(self, rocket, bullet, time, random):
clone_x = random
clone_y = 0
clone_rect = pygame.Rect(clone_x, clone_y, self.enemy_width, self.enemy_height)
pygame.draw.rect(screen, enemy_color, self.enemy_rect)
self.enemy_y += self.enemy_speed
self.enemy_rect.topleft = (self.enemy_x, self.enemy_y)
# Time Management and clone drawing
if has_passed == True:
pygame.draw.rect(screen, enemy_color, clone_rect)
rocket = ROCKET()
bullet = BULLET()
enemy = ENEMY()
randomNum = random.randint(enemyWidth, screen_width - enemyWidth)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Time Management
time1 = time.time()
elapse = time1 - time0
if elapse > 3:
time0 = time1
has_passed = True
else:
has_passed = False
screen.fill(bg_color)
rocket.draw_rocket()
rocket.move_rocket()
bullet.draw_bullet(rocket, bullet)
enemy.draw_enemy(rocket, bullet, has_passed, randomNum)
pygame.display.flip()
clock.tick(60)
还是这个?
({
/* Code here */
}()) == ()
或者这个来自 JS?
({
print("hi")
}()).self