Dynamically Create AutoHotkey Hotkey to Function/Subroutine - function

The AutoHotkey command Hotkey allows for the creation of dynamic hotkeys at runtime, but its syntax and documentation seems to limit it to built-in or existing labels/subroutines, which makes it much less useful:
Hotkey, KeyName [, Label, Options]
Is there a way to get it to work like regular, hard-coded hotkeys? For example:
#z::MsgBox foobar ; Typical, hard-coded hotkey pops up a message-box
Hotkey, z, MsgBox foobar ; Nope; complains about missing label “MsgBox foobar”
It looks like it might be possible due to the following line from the manual, however it is not clear how it would work:
Label - Both normal labels and hotkey/hotstring labels can be used.

This is a refinement of FakeRainBrigand's answer. It is used exactly the same:
Hotkey("x", "Foo", "Bar") ; this defines: x:: Foo("Bar")
Changes from the original:
Prevent accidental auto-execute of the handler subroutine by tucking it into the function.
Allowing me to reduce namespace pollution by narrowing the scope of the hotkeys variable from global to static.
Optimizations: fun is looked up only once (using Func()) at hotkey definition time; At invocation time, object lookups reduced four to two by splitting hotkeys into two objects funs and args;
This still relies of course on the _L version of AutoHotKey because of Object notation and variadic arg* syntax.
Hotkey(hk, fun, arg*) {
Static funs := {}, args := {}
funs[hk] := Func(fun), args[hk] := arg
Hotkey, %hk%, Hotkey_Handle
Return
Hotkey_Handle:
funs[A_ThisHotkey].(args[A_ThisHotkey]*)
Return
}

Doing exactly what you want isn't possible in AutoHotkey. This is the closest way I can think of.
Call this file Hotkeys.ahk, and put it in My Documents/AutoHotkey/Lib. Alternatively make a folder called Lib, and put it in the same directory as your main script.
Hotkeys := {}
Hotkey(hk, fun, p*) {
global hotkeys
hotkeys[hk] := {}
hotkeys[hk].fun := fun
hotkeys[hk].p := p
Hotkey, %hk%, HandleHotkey
}
HandleHotkey:
hotkeys[A_ThisHotkey].fun(hotkeys[A_ThisHotkey].p*)
return
Here's an example script that you could use it with.
Hotkey("e", "msgbox", "foobar")
MsgBox(msg) {
msgbox % msg
}
#Include <Hotkeys>
The first parameter is the hotkey, the second is the function to call, and everything after that is passed to the function.

Is this what you are looking for?
#Persistent
#SingleInstance Force
#installKeybdHook
Hotkey, #z, MyLabel
MyLabel:
MsgBox,OK
Return

With newer ahk version you can now use functions as label argument. See https://www.autohotkey.com/docs/commands/Hotkey.htm

Related

How to use a signal as function parameter in CAPL

I am trying to write a function in CAPL that takes a signal and calculates the physical value with the signal value, the signal factor and the signal offset.
This is how a simple gateway normally works:
message CAN1.myMessage1 myMessage1 = {DIR = RX};//message from the database
message CAN2.myMessage2 myMessage2 = {DIR = TX};//another message from the database
on message CAN1.*
{
if(this.id == myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = myMessage1.mySignalA * myMessage1.mySignalA.factor + myMessage1.mySignalA.offset;
}
}
And this is what I am trying to do:
...
on message CAN1.*
{
if(this.id ==myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = PhysicalValue(myMessage1.mySignalA);
}
}
double PhysicalValue(signal * s)
{
return s*s.factor+s.offset;
}
There are two problems with this code:
Firstly when I pass the signal as the parameter the compiler says that the types don't match. The second problem is that inside the function the attributes (factor and offset) are no longer recognized.
These problems might have something to do with the weird object-oriented-but-not-really nature of CAPL. The value of the signals can be accessed directly but it also has attributes?
int rawValue = myMessage1.mySignalA;
If you are familiar with C you might say that the problem is that I am specifying a pointer in the function but that I am not passing a pointer into it. But in CAPL there are no pointers and the * simply means anything.
Without the * I would have needed to use a specific signal which would have defeated the purpose of the function.
EDIT:
I have found the attribute .phys by now which does exactly what my demo function would have done.
double physValue = myMessage1.mySignalA.phys;
This has already made my code much shorter but there are other operations that I need to perform for multiple signals so being able to use signals as a function parameter would still be useful.
What you can do is this:
double PhysicalValue(signal * s)
{
// access signal by prepending a $
return $s.phys;
}
Call like this
on message CAN1.*
{
if(this.id ==myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = PhysicalValue(CAN1::myMessage1::mySignalA);
}
}
I.e. when you call your function, you have to provide the qualified name of the signal (with colons rather than dots). To my knowledge it is not possible to use myMessage1.mySignalA, since signals itself are not a CAPL datatype.
Apart from this, you might re-think whether you really should be using on message, but rather switch to on signal. Handling the signal values no matter with which message they are sent is done by CANoe's signal server.
Note that CANoe already has a function which does exactly what you're trying to do (multiplying by factor and adding offset). It's called getSignal:
on message CAN1.*
{
if(this.id == myMessage1.id)
{
myMessage2.mySignalB = getSignal(myMessage1::mySignalA);
}
}
Offsets and factors are defined in e.g. the DBC files.

Error : 'x' undefined

I got a problem with running Octave function (ODE), I've tried already present solutions for this problem but nothing is working. I've also tried by saving my filename as egzamin.m but it too not worked.
Code from octave :
function dx=egzamin(x,t)
dx=zeros(4,1);
b=0;
g=9.81;
x1=x(1);
y1=x(2);
Vx=x(3);
Vy=x(4);
dx(1)=Vx;
dx(2)=Vy;
dx(3)=-b*Vx*sqrt(Vx.^2+Vy.^2);
dx(4)=-b*Vy*sqrt(Vx.^2+Vy.^2)-g;
endfunction
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
The error is :
error: 'x' undefined near line 5 column 4
error: called from
egzamin at line 5 column 3
Since the file starts with function, it is not a script file,
as explained in the doc:
Unlike a function file, a script file must not begin with the keyword
function
Add any statement (even dummy like 1;) before the function line to get a script file.
# dummy statement to get a script file instead of a function file
1;
function dx=egzamin(x,t)
g = 9.81;
Vx = x(3);
Vy = x(4);
dx = [Vx, Vy, 0, -g];
endfunction
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
A very clear explanation of what's going on is given here.
You need to save the function (thus from function to endfunction and naught else) as egzamin.m, and then execute the rest of the code in a script or at the command line. Alternatively, provided Octave does that the same as what MATLAB does nowadays, first put your script (N=(..) to plot()) and then the function.
This is necessary since you are defining your function first, so it doesn't have any inputs yet, as you don't define them until later. The function needs to have its inputs defined before it executes, hence you need to save your function separately.
You can of course save your "script" bit, thus everything which is currently below your function declaration, as a function as well, simply don't give it in- and outputs, or, set all the input parameters here as well. (Which I wouldn't do as it's the same as your
egzamin then.) e.g.
function []=MyFunc()
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
endfunction

Mysterious stackoverflow in function call?

I'm creating a Lua program and I tried to use something like inheritance, but I got a stack overflow when I called the super of the function.
function Parent()
local self = {}
self.println = function(text) print(text) end
return self
end
function Child()
local super = Parent()
local this = {}
this.println = function(text)
super.println(text) -- According to the debugger, here is the problem.
print("Child")
end
for k, v in pairs(this) do
super[k] = v
end
return this
end
local a = Child()
a.println("Hello!")
I know there are other ways to do this, but I must use this kind of "OOP". Can anyone recommend me anything?
Your problem is with the loop that makes all println functions be the same println function that redirects the call to another printnl function, which is actually the same print function, creating a loop.
for k, v in pairs(this) do
super[k] = v
end
Removing that loop will make the code work, but I am not sure if this makes it behave as you wanted.
Maybe you should take a look at lua metatables if you want to inherit methods.
That for k, v in pairs(this) do loop seems backwards to me.
You are pushing the this copies of the functions into the super table (overwriting the ones that are already there).
So you push this.println into super and then call super.println inside it and you end up calling yourself repeatedly.
Did you mean to do that the other way around? Copy the super functions into this? Or what was the point with that loop in the first place?

Error generating localized variables (as constants)

The usage message for Set reminds us that multiple assignments can easily be made across two lists, without having to rip anything apart. For example:
Remove[x1, x2, y1, y2, z1, z2];
{x1, x2} = {a, b}
Performs the assignment and returns:
{a, b}
Thread, commonly used to generate lists of rules, can also be called explicitly to achieve the same outcome:
Thread[{y1, y2} = {a, b}]
Thread[{z1, z2} -> {a, b}]
Gives:
{a, b}
{z1 -> a, z2 -> b}
However, employing this approach to generate localized constants generates an error. Consider this trivial example function:
Remove[f];
f[x_] :=
With[{{x1, x2} = {a, b}},
x + x1 + x2
]
f[z]
Here the error message:
With::lvset: "Local variable specification {{x1,x2}={a,b}} contains
{x1,x2}={a,b}, which is an assignment to {x1,x2}; only assignments
to symbols are allowed."
The error message documentation (ref/message/With/lvw), says in the 'More Information' section that, "This message is generated when the first element in With is not a list of assignments to symbols." Given this explanation, I understand the mechanics of why my assignment failed. Nonetheless, I'm puzzled and wondering if this is necessary restriction by WRI, or a minor design oversight that should be reported.
So here's my question:
Can anyone shed some light on this behavior and/or offer a workaround? I experimented with trying to force Evaluation, without luck, and I'm not sure what else to try.
What you request is tricky. This is a job for macros, as already exposed by the others. I will explore a different possibility - to use the same symbols but put some wrappers around the code you want to write. The advantage of this technique is that the code is transformed "lexically" and at "compile-time", rather than at run-time (as in the other answers). This is generally both faster and easier to debug.
So, here is a function which would transform the With with your proposed syntax:
Clear[expandWith];
expandWith[heldCode_Hold] :=
Module[{with},
heldCode /. With -> with //. {
HoldPattern[with[{{} = {}, rest___}, body_]] :>
with[{rest}, body],
HoldPattern[
with[{
Set[{var_Symbol, otherVars___Symbol}, {val_, otherVals___}], rest___},
body_]] :>
with[{{otherVars} = {otherVals}, var = val, rest}, body]
} /. with -> With]
Note that this operates on held code. This has the advantage that we don't have to worry about possible evaluation o the code neither at the start nor when expandWith is finished. Here is how it works:
In[46]:= expandWith#Hold[With[{{x1,x2,x3}={a,b,c}},x+x1+x2+x3]]
Out[46]= Hold[With[{x3=c,x2=b,x1=a},x+x1+x2+x3]]
This is, however, not very convenient to use. Here is a convenience function to simplify this:
ew = Function[code, ReleaseHold#expandWith#Hold#code, HoldAll]
We can use it now as:
In[47]:= ew#With[{{x1,x2}={a,b}},x+x1+x2]
Out[47]= a+b+x
So, to make the expansion happen in the code, simply wrap ew around it. Here is your case for the function's definition:
Remove[f];
ew[f[x_] := With[{{x1, x2} = {a, b}}, x + x1 + x2]]
We now check and see that what we get is an expanded definition:
?f
Global`f
f[x_]:=With[{x2=b,x1=a},x+x1+x2]
The advantage of this approach is that you can wrap ew around an arbitrarily large chunk of your code. What happens is that first, expanded code is generated from it, as if you would write it yourself, and then that code gets executed. For the case of function's definitions, like f above, we cansay that the code generation happens at "compile-time", so you avoid any run-time overhead when usin the function later, which may be substantial if the function is called often.
Another advantage of this approach is its composability: you can come up with many syntax extensions, and for each of them write a function similar to ew. Then, provided that these custom code-transforming functions don't conlict with each other, you can simply compose (nest) them, to get a cumulative effect. In a sense, in this way you create a custom code generator which generates valid Mathematica code from some Mathematica expressions representing programs in your custom languuage, that you may create within Mathematica using these means.
EDIT
In writing expandWith, I used iterative rule application to avoid dealing with evaluation control, which can be a mess. However, for those interested, here is a version which does some explicit work with unevaluated pieces of code.
Clear[expandWithAlt];
expandWithAlt[heldCode_Hold] :=
Module[{myHold},
SetAttributes[myHold, HoldAll];
heldCode //. HoldPattern[With[{Set[{vars__}, {vals__}]}, body_]] :>
With[{eval =
(Thread[Unevaluated[Hold[vars] = Hold[vals]], Hold] /.
Hold[decl___] :> myHold[With[{decl}, body]])},
eval /; True] //. myHold[x_] :> x]
I find it considerably more complicated than the first one though.
The tricky issue is to keep the first argument of Set unevaluated.
Here is my suggestion (open to improvements of course):
SetAttributes[myWith, HoldAll];
myWith[{s : Set[a_List, b_List]}, body_] :=
ReleaseHold#
Hold[With][
Table[Hold[Set][Extract[Hold[s], {1, 1, i}, Hold],
Extract[Hold[s], {1, 2, i}]], {i, Length#b}], Hold#body]
x1 = 12;
Remove[f];
f[x_] := myWith[{{x1, x2} = {a, b}}, x + x1 + x2]
f[z]
results in
a+b+z
Inspired by halirutan below I think his solution, made slightly more safely, is equivalent to the above:
SetAttributes[myWith, HoldAll];
myWith[{Set[a : {__Symbol}, b_List]} /; Length[a] == Length[b],
body_] :=
ReleaseHold#
Hold[With][
Replace[Thread[Hold[a, b]], Hold[x_, y_] :> Hold[Set[x, y]], 1],
Hold#body]
The tutorial "LocalConstants" says
The way With[{x=Subscript[x, 0],...},body] works is to take body, and replace every
occurrence of x, etc. in it by Subscript[x, 0], etc. You can think of With as a
generalization of the /. operator, suitable for application to Mathematica code instead of
other expressions.
Referring to this explanation it seems obvious that something like
x + x1 + x2 /. {x1, x2} -> {a, b}
will not work as it might be expected in the With notation.
Let's assume you really want to hack around this. With[] has the attribute HoldAll, therefore everything you give as first parameter is not evaluated. To make such a vector-assignment work you would have to create
With[{x1=a, x2=b}, ...]
from the vector-notation. Unfortunately,
Thread[{a, b} = {1, 2}]
does not work because the argument to Thread is not held and the assignment is evaluated before Thread can do anything.
Lets fix this
SetAttributes[myThread, HoldFirst];
myThread[Set[a_, b_]] := mySet ### Transpose[{a, b}]
gives
In[31]:= myThread[{a, b, c} = {1, 2, 3}]
Out[31]= {mySet[a, 1], mySet[b, 2], mySet[c, 3]}
What looks promising at first, just moved the problem a bit away. To use this in With[] you have to replace at some point the mySet with the real Set. Exactly then, With[] does not see the list {a=1, b=2, c=3} but, since it has to be evaluated, the result of all assignments
In[32]:= With[
Evaluate[myThread[{a, b, c} = {1, 2, 3}] /. mySet :> Set], a + b + c]
During evaluation of In[32]:= With::lvw: Local
variable specification {1,2,3} contains 1, which is not an assignment to a symbol. >>
Out[32]= With[{1, 2, 3}, a + b + c]
There seems to be not easy way around this and there is a second question here: If there is a way around this restriction, is it as fast as With would be or do we lose the speed advantage compared to Module? And if speed is not so important, why not using Module or Block in the first place?
You could use Transpose to shorten Rolfs solution by 100 characters:
SetAttributes[myWith, HoldAll];
myWith[{Set[a_List, b_List]}, body_] :=
ReleaseHold[Hold[With][Hold[Set[#1, #2]] & ### Transpose[{a, b}],
Hold#body
]]
#Heike, yep the above breaks if either variable has already a value. What about this:
SetAttributes[myWith, HoldAll];
myWith[{Set[a_List, b_List]}, body_] :=
ReleaseHold#
Hold[With][Thread[Hold[a, b]] /. Hold[p__] :> Hold[Set[p]],
Hold#body]

Passing variables into a function in Lua

I'm new to Lua, so (naturally) I got stuck at the first thing I tried to program. I'm working with an example script provided with the Corona Developer package. Here's a simplified version of the function (irrelevant material removed) I'm trying to call:
function new( imageSet, slideBackground, top, bottom )
function g:jumpToImage(num)
print(num)
local i = 0
print("jumpToImage")
print("#images", #images)
for i = 1, #images do
if i < num then
images[i].x = -screenW*.5;
elseif i > num then
images[i].x = screenW*1.5 + pad
else
images[i].x = screenW*.5 - pad
end
end
imgNum = num
initImage(imgNum)
end
end
If I try to call that function like this:
local test = slideView.new( myImages )
test.jumpToImage(2)
I get this error:
attempt to compare number with nil
at line 225. It would seem that "num" is not getting passed into the function. Why is this?
Where are you declaring g? You're adding a method to g, which doesn't exist (as a local). Then you're never returning g either. But most likely those were just copying errors or something. The real error is probably the notation that you're using to call test:jumpToImage.
You declare g:jumpToImage(num). That colon there means that the first argument should be treated as self. So really, your function is g.jumpToImage(self, num)
Later, you call it as test.jumpToImage(2). That makes the actual arguments of self be 2 and num be nil. What you want to do is test:jumpToImage(2). The colon there makes the expression expand to test.jumpToImage(test, 2)
Take a look at this page for an explanation of Lua's : syntax.