GodetteAI you need to assign the lambda function to a variable

That much is correct, but the rest of GodetteAI's post seems to be in some language other than GDScript. She apparently doesn't know that the question concerns GDScript in Godot 4 unless that's stated in the post.

Here's how to define and call a lambda function in GDScript:
https://docs.godotengine.org/en/4.0/tutorials/scripting/gdscript/gdscript_basics.html#lambda-functions

oobiekanoobie gdscript is similar to python in this regard. I think you can do

var the_timeout = func(): print(2)
$node.connect(the_timeout)

or just $node.connect(func(): print(2))

but if you need more than a one-liner you have to define a separate function.

I think the idiomatic gdscript solution is to wrap your vars and functions in a class, though.

  • xyz replied to this.

    synthnostate Lambdas can have any number of lines. Otherwise they wouldn't be of much use.

    (func():
    	for n in 10:
    		print(n)
    ).call()

    oobiekanoobie Your question is really not clear. The code image you posted does not communicate what you want to do and bot's inept response on lambdas only muddied the water more. So try to be more punctual with your question (what exactly are you're trying to accomplish) and post some actual code.

      xyz Okay, here is the code

      extends Control
      
      var textToReveal: String = "This is the text to be revealed"
      var STATUS_PROCESS : bool
      var STATUS_DONE : bool
      var revealInterval: float = 0.05
      var visible_letters : int = 0
      var pressed_z = 0
      
      func _ready():
      	$Timer.wait_time = revealInterval
      	STATUS_DONE = true
      	STATUS_PROCESS = false
      
      func _input(event):
      	if STATUS_DONE == true:
      			if event.is_action_pressed("ui_accept"):
      				pressed_z += 1
      				if pressed_z == 1:
      					$Label.text = ""
      					visible_letters = 0
      					$Timer.start()
      					STATUS_DONE = false
      					STATUS_PROCESS = true
      				elif pressed_z == 2:
      					visible_letters = 0
      					pressed_z = 0
      					STATUS_DONE = true
      					$Label.text = ""
      	elif STATUS_DONE == false:
      		if Input.is_action_just_released("ui_accept"):
      			if pressed_z == 1:
      				$Label.text = textToReveal
      				$Timer.stop()
      				STATUS_DONE = true
      				STATUS_PROCESS = false
      				print("Skipped text")
      func _on_timer_timeout():
      	if visible_letters < textToReveal.length():
      		var letter = textToReveal[visible_letters]
      		$Label.text += letter
      		if letter != " ":  
      			$AudioStreamPlayer.play()
      			visible_letters += 1
      		elif letter == " ":
      			visible_letters += 1
      	else:
      		STATUS_DONE = true
      		print("Printing finished")
      		$Timer.stop()

      I am trying to make that a global function, but the downsides are it requires a AudioStreamPlayer, a Label and a Timer. I tried to make it so I make a global variable that integrates the timeout inside the global function and uses variables as nodes. For the Label and AudioStreamPlayer I tried replacements that are working properly but the timer won't work and the lambas thing is a bit confusing. Can I make that whole process into a single function?
      btw, it is for making a dialogue that is written progressively, like in Professor Layton

      • xyz replied to this.

        oobiekanoobie
        I'm not sure why exactly do you need a global function for that.
        Labels have visible_characters property. You can simply animate that (prefferrably with a tween). It'll make the whole thing much easier.

        And please format your code inside proper tags. It's hard to follow it this way.

        And please format your code inside proper tags. It's hard to follow it this way.

        To do that, place ~~~ on lines before and after the code. The </> icon at the bottom of the post is supposed to do that, but it doesn't always work correctly.

        My bad

        extends Control
        
        var textToReveal: String = "This is the text to be revealed"
        var STATUS_PROCESS : bool
        var STATUS_DONE : bool
        var revealInterval: float = 0.05
        var visible_letters : int = 0
        var pressed_z = 0
        
        func _ready():
                 $Timer.wait_time = revealInterval
                 STATUS_DONE = true
                 STATUS_PROCESS = false
        
        func _input(event):
            if STATUS_DONE == true:
            if event.is_action_pressed("ui_accept"):
                pressed_z += 1
                if pressed_z == 1:
                    $Label.text = ""
                    visible_letters = 0
                    $Timer.start()
                    STATUS_DONE = false
                    STATUS_PROCESS = true
                elif pressed_z == 2:
                    visible_letters = 0
                    pressed_z = 0
                    STATUS_DONE = true
                    $Label.text = ""
            elif STATUS_DONE == false:
                if Input.is_action_just_released("ui_accept"):
                    if pressed_z == 1:
                        $Label.text = textToReveal
                        $Timer.stop()
                        STATUS_DONE = true
                        STATUS_PROCESS = false
                        print("Skipped text")
        func _on_timer_timeout():
            if visible_letters < textToReveal.length():
                var letter = textToReveal[visible_letters]
                $Label.text += letter
                if letter != " ":
                    $AudioStreamPlayer.play()
                    visible_letters += 1
                elif letter == " ":
                    visible_letters += 1
                else:
                    STATUS_DONE = true
                    print("Printing finished")
                    $Timer.stop()

          oobiekanoobie Yeah, a "lambda" is a function without a name. It has access to the local variables of its parent function, which is what you want... I think.

            synthnostate Yep, that is pretty much what I want to do (integrating the timeout inside the main variable so work gets easier. Is there any good tutorial on it or do the docs explain it pretty well?

              oobiekanoobie Your code still has some indentation problems.
              If you want to make a typewriter effect on a label, here's how to do it by a single call from _ready() using a lambda signal callback:

              extends Label
              
              func _ready():
              	type_it("Type this text into a typewriter")
              
              func type_it(what: String, character_delay: float = .1):
              	self.text = what 
              	self.visible_characters = 0
              	var t = Timer.new()
              	add_child(t)
              	t.wait_time = character_delay
              	t.connect("timeout", func():
              		self.visible_characters += 1
              		if self.visible_characters == self.text.length():
              			t.queue_free()
              	)
              	t.start()

                xyz Ok thank you so much, that madew everything simpler! Have a nice day everyone who helped me 🙂

                oobiekanoobie Is there any good tutorial on it or do the docs explain it pretty well?

                The docs are decent. If you really want to learn all the tricks you can do with lambdas, learn some Javascript. They're usually called "closures" there btw. (Because they "enclose" the outer scope variables.)