functions defined in functions should properly close over upvalues the second time they are run #96

Open
opened 2025-07-10 21:06:57 +00:00 by kavi · 3 comments
Member
let alphabet = [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z]
let char_symbols_list = [["a", :a],["b", :b],["c", :c],["d", :d],["e", :e],["f", :f],["g", :g],["h", :h],["i", :i],["j", :j],["k", :k],["l", :l],["m", :m],["n", :n],["o", :o],["p", :p],["q", :q],["r", :r],["s", :s],["t", :t],["u", :u],["v", :v],["w", :w],["x", :x],["y", :y],["z", :z], [" ", :space]]

fn get_key_in_list {
  (a_key, []) -> :nil
  (a_key, a_dict) -> {
    let matches = filter(fn (x) -> eq?(a_key, first(x)), a_dict)
    if any?(matches) then second(first(matches)) else :nil
  }
}

fn char_symbol(a_char) -> get_key_in_list(a_char, char_symbols_list)

fn to_char_dict (str) -> {
  print!("Turning str to dict: {str}")
  let the_chars = chars(downcase(str))
  print!("Chars {the_chars}")
  let first_char = char_symbol(first(the_chars))
  print!("Starting with {first_char} of type", type(first_char))
  let the_symbols = map(char_symbol, the_chars)
  print!("As symbols: {the_symbols} with types ", type(the_symbols), type(first(the_symbols)))
  the_symbols
}

let sample_dict = #{:a 1, :b 2, :c 3, :o 14}
print!(char_symbol("c"))
let d = to_char_dict(downcase(trim("One must have a mind of winter")))
get(sample_dict,first(d))
``` let alphabet = [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z] let char_symbols_list = [["a", :a],["b", :b],["c", :c],["d", :d],["e", :e],["f", :f],["g", :g],["h", :h],["i", :i],["j", :j],["k", :k],["l", :l],["m", :m],["n", :n],["o", :o],["p", :p],["q", :q],["r", :r],["s", :s],["t", :t],["u", :u],["v", :v],["w", :w],["x", :x],["y", :y],["z", :z], [" ", :space]] fn get_key_in_list { (a_key, []) -> :nil (a_key, a_dict) -> { let matches = filter(fn (x) -> eq?(a_key, first(x)), a_dict) if any?(matches) then second(first(matches)) else :nil } } fn char_symbol(a_char) -> get_key_in_list(a_char, char_symbols_list) fn to_char_dict (str) -> { print!("Turning str to dict: {str}") let the_chars = chars(downcase(str)) print!("Chars {the_chars}") let first_char = char_symbol(first(the_chars)) print!("Starting with {first_char} of type", type(first_char)) let the_symbols = map(char_symbol, the_chars) print!("As symbols: {the_symbols} with types ", type(the_symbols), type(first(the_symbols))) the_symbols } let sample_dict = #{:a 1, :b 2, :c 3, :o 14} print!(char_symbol("c")) let d = to_char_dict(downcase(trim("One must have a mind of winter"))) get(sample_dict,first(d)) ```
Owner

There's a stack discipline problem with print!:

print! ("c")
map (even?, [1, 2, 3]) &=> ["1", "2", "3"]

Time to debug this!

There's a stack discipline problem with `print!`: ``` print! ("c") map (even?, [1, 2, 3]) &=> ["1", "2", "3"] ``` Time to debug this!
scott changed title from Having an issue with map, probably just a code error! to `print!` should observe stack discipline 2025-07-11 18:36:00 +00:00
scott added the
bug
label 2025-07-11 18:36:11 +00:00
Owner

New datum:

map (even?, [1, 2, 3])
print! ("c") & console=> "false"

More minimal example:

map (inc, [1, 2, 3])
map (dec, [1,2 , 3]) &=> [2, 3, 4]

What's happening is that fn mapper in map in prelude at line 276 is closing over inc as the function to apply in the mapper, but not re-closing dec the second time it's called.

fn map {
	"Maps a function over a list: returns a new list with elements that are the result of applying the function to each element in the original list. E.g., `map ([1, 2, 3], inc) &=> [2, 3, 4]`. With one argument, returns a function that is a mapper over lists; with two, it executes the mapping function right away."
	(f as :fn) -> map (f, _)
	(kw as :keyword) -> map (kw, _)
	(f as :fn, xs) -> {
		fn mapper (prev, curr) -> append (prev, f (curr)) &<-- closure error here
		fold (mapper, xs, [])
	}
	(kw as :keyword, xs) -> {
		fn mapper (prev, curr) -> append (prev, kw (curr))
		fold (mapper, xs, [])
	}
}
New datum: ``` map (even?, [1, 2, 3]) print! ("c") & console=> "false" ``` More minimal example: ``` map (inc, [1, 2, 3]) map (dec, [1,2 , 3]) &=> [2, 3, 4] ``` What's happening is that `fn mapper` in `map` in `prelude` at line 276 is closing over `inc` as the function to apply in the mapper, but not re-closing `dec` the second time it's called. ``` fn map { "Maps a function over a list: returns a new list with elements that are the result of applying the function to each element in the original list. E.g., `map ([1, 2, 3], inc) &=> [2, 3, 4]`. With one argument, returns a function that is a mapper over lists; with two, it executes the mapping function right away." (f as :fn) -> map (f, _) (kw as :keyword) -> map (kw, _) (f as :fn, xs) -> { fn mapper (prev, curr) -> append (prev, f (curr)) &<-- closure error here fold (mapper, xs, []) } (kw as :keyword, xs) -> { fn mapper (prev, curr) -> append (prev, kw (curr)) fold (mapper, xs, []) } } ```
scott changed title from `print!` should observe stack discipline to functions defined in functions should properly close over upvalues the second time they are run 2025-07-11 20:44:31 +00:00
Owner

Most minimal example:

fn foo (n) -> {
    fn bar () -> n
}

foo (:foo) ()
foo (:bar) ()
Most minimal example: ``` fn foo (n) -> { fn bar () -> n } foo (:foo) () foo (:bar) () ```
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: twc/ludus#96
No description provided.