AutoIt: Why can't I insert an element into an array using a function? - autoit

When I call the Bar function, the element is not inserted into the array passed as an argument.
Here is my code:
Foo ()
Func Foo ()
Local $Baz[100] = []
Call ("Bar", $Baz)
MsgBox (0, "", $Baz[0])
Return
EndFunc
Func Bar ($_Array)
$_Array[0] = 1
Return
EndFunc
Thank you very much for your help.

A function handles a "shadow copy" of the parameter (variable or array), unless you use ByRef (to tell the function to use/manipulate the given variable directly):
Foo ()
Func Foo ()
Local $Baz[100] = []
Bar($Baz)
MsgBox (0, "", $Baz[0])
Return
EndFunc
Func Bar (ByRef $_Array)
$_Array[0] = 1
Return
EndFunc
This doesn't work with call though.

Related

Call the more general method from a specific one

I am trying to call a general method from a specific one, but cannot figure out how.
function fn(x)
# generic
...
end
function fn(x :: String)
# I want to call the generic version here
val = fn(x)
# do something with val and then return it
...
end
Is this possible?
A workaround is using a helper function that can be called from both generic and specific methods. e.g.
function helper(x)
# main work is here
...
end
function fn(x)
# generic
helper(x)
end
function fn(x :: String)
val = helper(x)
# now use the val to do something
...
end
Without using such helpers, is there a way to control the dispatch to select a particular method to use? Is there something like :before and :after keywords and call-next-method from lisp CLOS in Julia?
You can use the invoke function:
julia> function fn(x)
#info "generic $x"
end
fn (generic function with 1 method)
julia> function fn(x :: String)
#info "before"
invoke(fn, Tuple{Any}, x)
#info "after"
end
fn (generic function with 2 methods)
julia> fn(10)
[ Info: generic 10
julia> fn("10")
[ Info: before
[ Info: generic 10
[ Info: after
(just to be clear - the printing of "before" and "after" is only to highlight what gets executed in what sequence - the only thing that is related to method dispatch here is the invoke function)

Writing the function "once" in Elixir

I'm coming to Elixir from primarily a Javascript background. in JS, it's possible to write a higher order function "once" which returns a function that will invoke the passed in function only once, and returns the previous result on subsequent calls- the trick is manipulating variables that were captured via closure:
var once = (func) => {
var wasCalled = false, prevResult;
return (...args) => {
if (wasCalled) return prevResult;
wasCalled = true;
return prevResult = func(...args);
}
}
It seems to me that it's not possible to create this function in Elixir, due to its different variable rebinding behavior. Is there some other clever way to do it via pattern matching or recursion, or is it just not possible? Without macros that is, I'd imagine those might enable it. Thanks
Using the current process dictionary:
defmodule A do
def once(f) do
key = make_ref()
fn ->
case Process.get(key) do
{^key, val} -> val
nil ->
val = f.()
Process.put(key, {key, val})
val
end
end
end
end
Or if the function will be passed across processes, an ets table can be used:
# ... during application initialization
:ets.new(:cache, [:set, :public, :named_table])
defmodule A do
def once(f) do
key = make_ref()
fn ->
case :ets.lookup(:cache, key) do
[{^key, val}] -> val
[] ->
val = f.()
:ets.insert(:cache, {key, val})
val
end
end
end
end
Application.put_env / Application.get_env can also be used to hold global state, though usually is used for configuration settings.
It's not considered idiomatic in most cases, but you can do this with Agent:
defmodule A do
def once(fun) do
{:ok, agent} = Agent.start_link(fn -> nil end)
fn args ->
case Agent.get(agent, & &1) do
nil ->
result = apply(fun, args)
:ok = Agent.update(agent, fn _ -> {:ok, result} end)
result
{:ok, result} ->
result
end
end
end
end
Now if you run this:
once = A.once(fn sleep ->
:timer.sleep(sleep)
1 + 1
end)
IO.inspect once.([1000])
IO.inspect once.([1000])
IO.inspect once.([1000])
IO.inspect once.([1000])
You'll see that the first line is printed after 1 second, but the next 3 are printed instantly, because the result is fetched from the agent.
While both already given answers are perfectly valid, the most precise translation from your javascript is shown below:
defmodule M do
use GenServer
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def init(_args) do
Process.sleep(1_000)
{:ok, 42}
end
def value() do
start_link()
GenServer.call(__MODULE__, :value)
end
def handle_call(:value, _from, state) do
{:reply, state, state}
end
end
(1..5) |> Enum.each(&IO.inspect(M.value(), label: to_string(&1)))
Use the same metric as in #Dogbert’s answer: the first value is printed with a delay, all subsequent are printed immediately.
This is an exact analog of your memoized function using GenServer stage. GenServer.start_link/3 returns one of the following:
{:ok, #PID<0.80.0>}
{:error, {:already_started, #PID<0.80.0>}}
That said, it is not restarted if it’s already started. I do not bother to check the returned value since we are all set in any case: if it’s the initial start, we call the heavy function, if we were already started, the vaklue is already at fingers in the state.

Crystal - method pointers

Is is possible to use method pointers in Crystal ?
And if yes, how do I create and use them ?
I wish to store multiple instructions in an array and then call the required one later in the programm.
This is what Proc is for.
def foo()
puts "foo"
end
def bar()
puts "bar"
end
procs = {->foo, ->bar}
procs.each do |p|
p.call
end
outputs
foo
bar
See online: https://play.crystal-lang.org/#/r/2vb7
It also works with methods and static methods:
class A
def self.foo()
puts "A.foo"
end
def bar()
puts "bar"
end
end
proc = ->A.foo
puts proc
proc.call
a = A.new
proc = ->a.bar
proc.call
Read more in the official docs: https://crystal-lang.org/docs/syntax_and_semantics/literals/proc.html

VB6 Recursion and return variables in functions

This is a syntax question. I am confused as to when the "return variable" in a Function is used as a return variable or as a method call. For instance, if I have:
Function foo() As Boolean
foo = True
foo = foo And bar
End Function
Does the second line in this function act as a recursive call to foo, or does it resolve to true from the previous assignment?
To get the value as of the last assignment:
foo = foo And bar
To make a recursive call:
foo = foo() And bar
The () makes all the difference. (BTW, this applies to VBA too.)

Why is this recursion function parameter nil?

walk is a recursive function that walks the given tree and if walked over a file do something with it.
The "do something with it" should be changed.
I could use coroutine.yield(f) in walk but I wanted to know my mistake first.
As you see the argument lootfunc is given by a reference and should be called within walk.
But it gives me the error seen below. So why is the parameter lootfunc nil?
local KEYWORDS = {
"%.db[x]?",
"%.ojsn",
}
local function loot(d)
if MATCH == "path" then -- only look to the path not to the content
for i,keyword in pairs(KEYWORDS) do
if string.find(d,keyword) then
--coroutine.yield(d)
print(d)
end
end
end
end
local function walk (path,lootfunc)
for file in lfs.dir(path) do
if file ~= "." and file ~= ".." then
local f = path..'/'..file
local attr = lfs.attributes (f)
if(type(attr) == "table") then
if attr.mode == "directory" then
walk (f) -- next round
elseif attr.mode == "file" then
lootfunc(f)
end
end
end
end
end
walk("/path/",loot)
shadowed.lua:73: attempt to call local 'lootfunc' (a nil value)
stack traceback:
(command line):1: in function 'lootfunc'
shadowed.lua:73: in function 'walk'
shadowed.lua:71: in function 'walk'
shadowed.lua:71: in function 'walk'
shadowed.lua:88: in main chunk
[C]: in function 'dofile'
(command line):1: in function <(command line):1>
[C]: in function 'xpcall'
(command line):1: in main chunk
[C]: ?
You are calling walk(f) in the function walk, there's only one argument, the second argument is filled with nil, so change:
if attr.mode == "directory" then
walk(f) -- next round
to
if attr.mode == "directory" then
walk(f, lootfunc) -- next round

Resources