1 ## oils_failures_allowed: 1
2 ## our_shell: ysh
3
4 # dynamically generate procs
5
6 #### with eval builtin command, in global scope
7
8 for param in a b {
9 eval """
10 proc echo_$param(prefix) {
11 echo \$prefix $param
12 }
13 """
14 }
15
16 echo_a prefix
17 echo_b prefix
18
19 ## STDOUT:
20 prefix a
21 prefix b
22 ## END
23
24 #### with eval builtin command, in local scope
25
26 proc p {
27 for param in a b {
28 eval """
29 proc echo_$param(prefix) {
30 echo \$prefix $param
31 }
32 """
33 }
34
35 echo_a prefix
36 echo_b prefix
37 }
38
39 p
40
41 echo_a prefix # not available here!
42
43 ## status: 127
44 ## STDOUT:
45 prefix a
46 prefix b
47 ## END
48
49 #### with parseCommand() then io->eval(), in local scope
50
51 proc p {
52 var result = {}
53 for param in a b {
54 var s = """
55 proc echo_$param(prefix) {
56 echo \$prefix $param
57 }
58 """
59 var cmd = parseCommand(s)
60 call io->eval(cmd)
61 }
62
63 echo_a prefix
64 echo_b prefix
65 }
66
67 p
68
69 echo_a prefix
70
71 ## status: 127
72 ## STDOUT:
73 prefix a
74 prefix b
75 ## END
76
77 #### with parseCommand() then io->eval(cmd, vars={out_dict: {}})
78
79 # This could take the place of evalToDict()? But evalToDict() is useful in
80 # Hay?
81
82 func genProcs() {
83 var vars = {out_dict: {}}
84 for param in a b {
85 var s = """
86 proc echo_$param(prefix) {
87 echo \$prefix $param
88 }
89 setvar out_dict.echo_$param = echo_$param
90 """
91 var cmd = parseCommand(s)
92 call io->eval(cmd, vars=vars)
93 }
94 return (vars.out_dict)
95 }
96
97 var procs = genProcs()
98
99 var my_echo_a = procs.echo_a
100 var my_echo_b = procs.echo_b
101
102 my_echo_a prefix
103 my_echo_b prefix
104
105 ## STDOUT:
106 prefix a
107 prefix b
108 ## END
109
110 #### with evalToDict()
111
112 func genProcs() {
113 var result = {}
114 for param in a b {
115 var s = """
116 # This is defined locally
117 proc echo_$param(prefix) {
118 echo \$prefix $param
119 }
120 if false {
121 = echo_$param
122 var a = 42
123 pp frame_vars_
124 }
125 """
126 var cmd = parseCommand(s)
127
128 var d = io->evalToDict(cmd)
129
130 # accumulate
131 setvar result["echo_$param"] = d["echo_$param"]
132 }
133 return (result)
134 }
135
136 var procs = genProcs()
137
138 var my_echo_a = procs.echo_a
139 var my_echo_b = procs.echo_b
140
141 my_echo_a prefix
142 my_echo_b prefix
143
144 ## STDOUT:
145 prefix a
146 prefix b
147 ## END
148
149
150 #### with runtime REFLECTION via __invoke__ - no parsing
151
152 # self is the first typed arg
153 proc p (prefix; self) {
154 echo $prefix $[self.param]
155 }
156
157 # p is invoked with "self", which has self.param
158 var methods = Object(null, {__invoke__: p})
159
160 var procs = {}
161 for param in a b {
162 setvar procs["echo_$param"] = Object(methods, {param: param})
163 }
164
165 var my_echo_a = procs.echo_a
166 var my_echo_b = procs.echo_b
167
168 # Maybe show an error if this is not value.Obj?
169 my_echo_a prefix
170 my_echo_b prefix
171
172 ## STDOUT:
173 prefix a
174 prefix b
175 ## END