IIFE在Swift语言中

时间:2014-06-04 16:54:16

标签: swift iife

在javascript中我们经常使用IIFE。像

这样的东西
(function() {
    ...do stuff to avoid dirtying scope.
}());

Swift中有闭包,函数是第一类对象。我的问题是:Swift中是否有相同的IIFE?

6 个答案:

答案 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())

enter image description here

答案 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