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 eval builtin command, making them global with names() and setVar()
50
51 func genProcs() {
52 var result = {}
53 for param in a b {
54 eval """
55 proc echo_$param(prefix) {
56 echo \$prefix $param
57 }
58 """
59 setvar result["echo_$param"] = getVar("echo_$param")
60 }
61
62 echo 'local'
63 echo_a prefix
64 echo_b prefix
65 echo
66
67 return (result)
68 }
69
70 var procs = genProcs()
71
72 # bind to global scope
73 for name in (procs) {
74 call setVar("my_$name", procs[name])
75 }
76
77 echo 'global'
78 my_echo_a prefix
79 my_echo_b prefix
80
81 ## STDOUT:
82 local
83 prefix a
84 prefix b
85
86 global
87 prefix a
88 prefix b
89 ## END
90
91 #### with parseCommand() then io->eval(), in local scope
92
93 proc p {
94 var result = {}
95 for param in a b {
96 var s = """
97 proc echo_$param(prefix) {
98 echo \$prefix $param
99 }
100 """
101 var cmd = parseCommand(s)
102 call io->eval(cmd)
103 }
104
105 echo_a prefix
106 echo_b prefix
107 }
108
109 p
110
111 echo_a prefix
112
113 ## status: 127
114 ## STDOUT:
115 prefix a
116 prefix b
117 ## END
118
119 #### with parseCommand() then io->eval(cmd, vars={out_dict: {}})
120
121 # This could take the place of evalToDict()? But evalToDict() is useful in
122 # Hay?
123
124 func genProcs() {
125 var vars = {out_dict: {}}
126 for param in a b {
127 var s = """
128 proc echo_$param(prefix) {
129 echo \$prefix $param
130 }
131 setvar out_dict.echo_$param = echo_$param
132 """
133 var cmd = parseCommand(s)
134 call io->eval(cmd, vars=vars)
135 }
136 return (vars.out_dict)
137 }
138
139 var procs = genProcs()
140
141 var my_echo_a = procs.echo_a
142 var my_echo_b = procs.echo_b
143
144 my_echo_a prefix
145 my_echo_b prefix
146
147 ## STDOUT:
148 prefix a
149 prefix b
150 ## END
151
152 #### with evalToDict()
153
154 func genProcs() {
155 var result = {}
156 for param in a b {
157 var s = """
158 # This is defined locally
159 proc echo_$param(prefix) {
160 echo \$prefix $param
161 }
162 if false {
163 = echo_$param
164 var a = 42
165 pp frame_vars_
166 }
167 """
168 var cmd = parseCommand(s)
169
170 var d = io->evalToDict(cmd)
171
172 # accumulate
173 setvar result["echo_$param"] = d["echo_$param"]
174 }
175 return (result)
176 }
177
178 var procs = genProcs()
179
180 var my_echo_a = procs.echo_a
181 var my_echo_b = procs.echo_b
182
183 my_echo_a prefix
184 my_echo_b prefix
185
186 ## STDOUT:
187 prefix a
188 prefix b
189 ## END
190
191
192 #### with runtime REFLECTION via __invoke__ - no parsing
193
194 # self is the first typed arg
195 proc p (prefix; self) {
196 echo $prefix $[self.param]
197 }
198
199 # p is invoked with "self", which has self.param
200 var methods = Object(null, {__invoke__: p})
201
202 var procs = {}
203 for param in a b {
204 setvar procs["echo_$param"] = Object(methods, {param: param})
205 }
206
207 var my_echo_a = procs.echo_a
208 var my_echo_b = procs.echo_b
209
210 if false {
211 = my_echo_a
212 = my_echo_b
213 type -t my_echo_a
214 type -t my_echo_b
215 }
216
217 # Maybe show an error if this is not value.Obj?
218 my_echo_a prefix
219 my_echo_b prefix
220
221 ## STDOUT:
222 prefix a
223 prefix b
224 ## END