编写一个返回自身的Swift函数

Pir*_*omo 2 recursion swift

我在Python中有这段代码:

def f(x, y):
    # do something...
    return f
Run Code Online (Sandbox Code Playgroud)

我试图在Swift中写这个,但无法弄清楚它是否可能.返回类型将变得无限长.

这是我试图用Python编写的游戏的一部分.这是一个具有多个评论功能的骰子游戏,可以在每一轮中调用.每轮完成后,评论函数可以返回自身,但也会有一些变化(例如在封闭范围内更改变量):

def say_scores(score0, score1):
    """A commentary function that announces the score for each player."""
    print("Player 0 now has", score0, "and Player 1 now has", score1)
    return say_scores

def announce_lead_changes(previous_leader=None):
    """Return a commentary function that announces lead changes."""

    def say(score0, score1):
        if score0 > score1:
            leader = 0
        elif score1 > score0:
            leader = 1
        else:
            leader = None
        if leader != None and leader != previous_leader:
            print('Player', leader, 'takes the lead by', abs(score0 - score1))
        return announce_lead_changes(leader)
    return say

def both(f, g):
    """Return a commentary function that says what f says, then what g says."""
    def say(score0, score1):
        return both(f(score0, score1), g(score0, score1))
    return say


def announce_highest(who, previous_high=0, previous_score=0):
    """Return a commentary function that announces when WHO's score
    increases by more than ever before in the game.
    assert who == 0 or who == 1, 'The who argument should indicate a player.'"""
    # BEGIN PROBLEM 7
    "*** YOUR CODE HERE ***"
    def say(score0,score1):
        scores = [score0,score1]
        score_diff = scores[who]-previous_score
        if score_diff > previous_high:
            print(score_diff,"point(s)! That's the biggest gain yet for Player",who)
            return announce_highest(who,score_diff,scores[who])
        return announce_highest(who,previous_high,scores[who])
    return say
    # END PROBLEM 7
Run Code Online (Sandbox Code Playgroud)

重复播放功能,直到某些玩家达到某个分数:

def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
         goal=GOAL_SCORE, say=silence):
    """Simulate a game and return the final scores of both players, with Player
    0's score first, and Player 1's score second.

    A strategy is a function that takes two total scores as arguments (the
    current player's score, and the opponent's score), and returns a number of
    dice that the current player will roll this turn.

    strategy0:  The strategy function for Player 0, who plays first.
    strategy1:  The strategy function for Player 1, who plays second.
    score0:     Starting score for Player 0
    score1:     Starting score for Player 1
    dice:       A function of zero arguments that simulates a dice roll.
    goal:       The game ends and someone wins when this score is reached.
    say:        The commentary function to call at the end of the first turn.
    """
    player = 0  # Which player is about to take a turn, 0 (first) or 1 (second)
    # BEGIN PROBLEM 5
    "*** YOUR CODE HERE ***"
    scores = [score0,score1]
    strategies = [strategy0,strategy1]
    while score0 < goal and score1 < goal:
        scores[player] += take_turn(strategies[player](scores[player], scores[other(player)]),
        scores[other(player)], dice)

        swap = is_swap(scores[player], scores[other(player)])
        player = other(player)
        if swap:
            scores[0],scores[1] = scores[1], scores[0]
        score0,score1 = scores[0],scores[1]
    # END PROBLEM 5
    # BEGIN PROBLEM 6
        "*** YOUR CODE HERE ***"
        say = say(score0,score1)
    # END PROBLEM 6
    return score0, score1
Run Code Online (Sandbox Code Playgroud)

Swe*_*per 8

让我们试着写下这样的话.

func f() {
    return f
}
Run Code Online (Sandbox Code Playgroud)

现在编译器抱怨因为f当它确实返回一些东西时没有声明返回任何东西.

好的,让我们尝试添加一个返回值类型,即一个不接受任何参数并且不返回任何参数的闭包.

func f() -> (() -> ()) {
    return f
}
Run Code Online (Sandbox Code Playgroud)

现在编译器抱怨f() -> (() -> ()),因此无法转换为() -> ().

我们应该编辑声明来返回一个() -> (() -> ()),对吧?

func f() -> (() -> (() -> ())) {
    return f
}
Run Code Online (Sandbox Code Playgroud)

现在f变成了一个() -> (() -> (() -> ())),无法转换成一个() -> (() -> ())!

现在看模式?这将永远持续下去.

因此,您只能以类型不安全的方式执行此操作,返回Any:

func f() -> Any { return f }
Run Code Online (Sandbox Code Playgroud)

用法:

func f() -> Any {
  print("Hello")
  return f
}
(f() as! (() -> Any))()
Run Code Online (Sandbox Code Playgroud)

之所以在python中这是可能的,正是因为Python是弱类型的,你不需要指定返回类型.

请注意,我不鼓励您在Swift中编写此类代码.在Swift中编写代码时,尝试用Swift思维方式解决问题.换句话说,您应该想到另一种解决不涉及此类功能的问题的方法.

  • @PirloLochisomo当你在Swift中编码时,你不应该考虑"如何在Python中解决这个问题?" 相反,尝试在不使用返回自身的函数的情况下解决问题. (3认同)