How do I use Smalltalk's built in Parser or Compiler to parse my own messages with optional parameters? - smalltalk

I'm trying to create a live-coding environment in Smalltalk. The objects I'm using have long complex methods with many parameters for creating new instances. I want to be able to write a very short "command" that just specifies the parameters I'm interested in and provides default values for all the other parameters.
For instance instead of writing something like:
Polyhedron shape: #cube size: 1 rotationSpeed: 5 rotationDirection: 0.707 color: red texture: false
In my live coding environment I want to write:
poly shape: #cube
Some of the arguments could be complex and contain their own messages like:
poly shape: #cube rotationSpeed: ((pot1 max: 0) min: speedLimit)
So rather than just trying to parse the live coding string myself I thought it would be easier if I could use Smalltalk's built in parser or compiler to decode the string and call Polyhedron with the full creation message including default values.
How would I do that?
I've got as far as getting an array of tokens out of the parser but that doesn't identify message parameters and arguments. Before I tried to implement argument parsing myself I figured there's likely to be something in Smalltalk that could give me a list of message parameters and arguments?

It doesn't look like you have to tweak the compiler. To provide default values simply have your objects be born with them. How? In the initialize method:
Polyhedron >> initialize
super initialize.
shape := #triangle.
size := 1.
rotationSpeed := 5.
rotationDirection := 0.707.
color: Color red texture: false
The #initialize message is sent when you send Polyhedron new. Thus, if you want to change the shape, you only need to send
Polyhedron new shape: #cube
Note by the way that it is usually a good idea to send super initialize so to give superclasses a chance to perform their initialization routines.
Note also that Polyhedra is the plural of Polyhedron, and class names are usually in singular.
Addendum
In case you cannot edit the class Polyhedron, you can still reference it and therefore send messages to it. In particular, you can create new instance creation methods, shorter than the ones you already have. Here is how to do this:
Polyedron compile: 'shape: aSymbol
^self
shape: aSymbol
size: 1
rotationSpeed: 5
rotationDirection: 0.707
color: Color rd texture: false'
Note that the argument of #compile: is the source code of the method you want to add. By using this new method you will be able to just say
Polyedron shape: #cube
to get what you wanted.

Related

Deserializing tuples with argument in Rust

I am a beginner in rust and working with some api that returns bytes that I can deserialize by defining their types.
result: (f64, f64, f64) = api.call();
Can I do the same by dynamically by passing a value n for the number of elements?
All elements of the tuple are of the same type. I would like to do something like this:
result: tuple(f64, 3) = api.call();
Here is the API of the call function.
Edit:
In case anyone ever encounters that issue in the future. I could deserialize the output by adopting this solution.
For reference: call() returns a Result<D: Detokenize, _>. Detokenize is mainly implemented for all T that implement Tokenizable.
All types that can receive the result are listed here.
Note that additional to tuples of various size, it's also implemented for:
impl<T: TokenizableItem + Clone, const N: usize> Tokenizable for [T; N]
Further, note that it is an async function with a Result, meaning you have to await it and deal with the potential error.
So you should(tm) be able to write:
result: [f64; 3] = api.call().await.unwrap();
Of course in a real project I would advise to replace unwrap() with some proper error handling.
Disclaimer: I don't know how to use the rest of ethers-core, so I'm unable to verify this in a test project. This information is purely derived from the documentation.
Static vs dynamic size
[f64; 3] requires you to know the number of elements at compile time.
Note that another Tokenizable is Vec<T>, meaning you could also specify Vec<T> as a result type. The length of this one will then be resolved at runtime, depending on how many elements of T the api.call() returns.
Further background information
Note that there is no such thing as a tuple that has N number of T elements, because a tuple is not a repetition of one type, it's a collection of types. Every element of a tuple can have a different type.
If you want to represent a repetition of one type, an array is what you really want. It's defined as one type T repeated N times: [T; N].

Modify Scilab/Xcos Block in Scilab 6 Gateway Function

I would like to modify an Xcos block from within a gateway function using the new (non-legacy) Scilab API, for example, replace the block's model property by a new model structure. In other words, do the same as the Scilab command(s):
m = scicos_model()
block.model = m
However, I did not manage to achieve this behavior with the functions from Scilab 6 API: a block created by standard_define() is correctly passed to my gateway function, where this argument is available as scilabVar of type 128. On the other hand, the Scilab help claims that a block is a "scilab tlist of type "Block" with fields : graphics, model, gui and doc".
Attempts
Assume scilabVar block taken from gateway function argument, string constants of type wchar_t[], scilabVar model holding the result of scicos_model():
Application of function scilab_setTListField (env, block, "model", model) returns error status (as its equivalents for MList and List do)
Knowing that property .model is at index 3, a setfield (3, model, block) called through scilab_call ("setfield", ...) also fails.
This is not surprising: when called directly from the Scilab command line, it ends up with
setfield: Wrong type for input argument #3: List expected. .
However, a getfield (3, block) works, so that at least read access to the block's data fields is possible.
An external helper function
function block = blockSetModel (block, model)
block.model = model
endfunction
also called through scilab_call("blockSetModel", ...) actually returns a block with changed model,
but the original block passed to this function remains unchanged.
Although ugly, this gives at least a way to construct an individual block structure
which needs to be returned as a copy.
Summary
So, is there simply a function missing in the API, which returns the TList (or whatever) behind a type 128 pointer variable?
Or is there any other approach to this problem I was unable to discover?
Background
The goal behind is to move the block definition task from the usual interfacing "gui" function (e.g. a Scilab script MyBlock.sci) into own C code. For this purpose, the interfacing function is reduced to a wrapper around a C gateway, which, for example, usesscilab_call ("standard_define",...) to create a new block when being called with parameter job=="define".
Modification of the contained model and graphics objects through the Scilab API works fine since these are standard list types. However, getting or setting these objects as attributes .model and .graphics of the
original block fails as described above.
Starting from Scilab/Xcos 6.0.0, the data-structure behind a block is no more an MList (or TList) so you cannot upgrade the model to your own MList. All the data behind are stored using a classical MVC within a C++ coded Block.hxx.
On each try you made, a serialization/deserialization happens to reconstruct the block model field as a Scilab value.
Could you describe what kind of field you want to append/edit regarding the block structure ? Some of the predefined fields might be enough to pass extra information.

Is type assignability too strict in JavaConstant.Dynamic.ofInvocation()?

I've read Rafael's article and am now doing awful, terrible things with JavaConstant.Dynamic. Mostly I'm getting a feel for how it works.
As part of these horrid experiments, I am turning an array of non-constant things into an array of JavaConstants. Then I'm invoking JavaConstant.Dynamic.ofInvocation(SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS, javaConstantsArray).
So, for example, something like this:
static final JavaConstant toJavaConstant(final Glorp[] glorps) {
final JavaConstant[] javaConstants = new JavaConstant[glorps.length];
for (int i = 0; i < javaConstants.length; i++) {
javaConstants[i] = toJavaConstant(glorps[i]); // another version of this method that works on scalars
}
return JavaConstant.Dynamic.ofInvocation(SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS, javaConstants);
}
ByteBuddy is telling me in the ofInvocation call that one of the JavaConstants in the varargs array I've passed it is not assignable to the parameter type of the SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS. I can understand this, because strictly speaking a variable arity method accepts an array as its last parameter, and a JavaConstant is not an array. But given that the SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS is ultimately resolved via the MethodHandle machinery with all of its argument adaptation and spreading tricks, I wonder: is this proactive assignability check "too much"? Should ByteBuddy take into account the varargs nature of the bootstrap method? Is there some other way to create an array or a list of an arbitrary number of scalar constants as a constant itself?
Yes, this was a bug and it will be fixed in Byte Buddy 1.10.18. Thanks for the patch!

How should I implement Obj C-like headers in Lua?

Now I have an import(a) function, that in short words dofile's header in .framework like this:
import("<Kakao/KARect>") => dofile("/System/Library/Frameworks/Kakao.framework/Headers/KARect.lua")
And in KARect.lua for example I have:
KARect = {}
function KARect:new(_x, _y, _width, _height, _colorBack)
local new = setmetatable({}, {__index = self})
new.id = KAEntities:generateID()
...
return new
end
function KARect:draw()
...
end
After some time I thought about reworking this system and making "headers" work like typical Lua modules with advanced require() so function will do e.g.:
import("<Kakao/KARect>") => package.path = "/System/Library/Frameworks/Kakao.framework/Headers/?.lua"; KARect = require("KARect")
and file will contain:
local KARect = {}
...
return KARect
Because headers should not contain anything but only classes with their names? I'm getting confused when thinking about it, as I never used Obj C :s
I never used Obj C
Then why are you trying to implement its headers in a language, that does not use headers at all?
Header! What is a header?
Header files in C-like languages store more than just a name. They store constants and macro commands, function and class method argument and return types, structure and class fields. In essence, the contents of the header file are forward declarations. They came into existence due to the need to perform the same forward-declarations across many files.
I don't know what additional rules and functions were added to header files in Obj-C, but you can get general understanding of what they do in the following links: 1, 2, 3, 4 with the last one being the most spot-on.
Answer to the question present
Lua is dynamically-typed interpreted language. It does not do compile time type checks and, typically, Lua programs can and should be structured in a way that does not need forward declarations across files. So there is no meaningful way for a programmer to create and for lua bytecode generator and interpreter to use header files.
Lua does not have classes at all. The code you've posted is a syntactic sugar for an assignment of a function with a slightly different signature to a table which imitates class:
KARect.new = function( first_arg_is_self, _x, _y, _width, _height, _colorBack)
local new = setmetatable({}, {__index = first_arg_is_self})
return new
end
There is no declarations here, only generation of an anonymous function and its assignment to a field in a table. Other parts of program do not need to know anything about a particular field, variable or function (which is stored in variable) in advance (unlike C).
So, no declaration means nothing to separate from implementation. You of course can first list fields of the class-table and do dummy assignments to them, but, again, Lua will have no use for those. If you want to give hints to humans, it is probably better to write a dedicated manual or put comments in the implementation.
Lua has situations where forward declarations are needed to reference local functions. But this situation does not arise in object oriented code, as all methods are accessed through reference to the object, and by the time first object is created, the class itself is usually fully constructed.

How to preallocate an array of class in MATLAB?

I have an array of objects in MATLAB and I've called their constructors in a loop:
antsNumber = 5;
for counter = 1: antsNumber
ant(counter) = TAnt(source, target);
end
MATLAB warns me to use preallocation to speed up the process. I do know the benefits of preallocation but I don't know how to do that for objects.
Here are a few options, which require that you design the class constructor for TAnt so that it is able to handle a no input argument case:
You can create a default TAnt object (by calling the constructor with no input arguments) and replicate it with REPMAT to initialize your array before entering your for loop:
ant = repmat(TAnt(),1,5); %# Replicate the default object
Then, you can loop over the array, overwriting each default object with a new one.
If your TAnt objects are all being initialized with the same data, and they are not derived from the handle class, you can create 1 object and use REPMAT to copy it:
ant = repmat(TAnt(source,target),1,5); %# Replicate the object
This will allow you to avoid looping altogether.
If TAnt is derived from the handle class, the first option above should work fine but the second option wouldn't because it would give you 5 copies of the handle for the same object as opposed to 5 handles for distinct objects.
The following link might be of help:
http://www.mathworks.com/help/techdoc/matlab_oop/brd4btr.html#brd4nrh
Web archive of dead link
New link:
http://de.mathworks.com/help/matlab/matlab_oop/creating-object-arrays.html
The warning it gives is superfluous, unless you are doing computational heavy stuff, I would ignore it.
The reason why it's giving you the error, is because it has to find new space. Say, I give you a list of seven objects, and I tell you that you need to place them all in a row, I then go off, and give you a few more things you need to put somewhere. I then give you an eighth object and tell you to put it right after the seventh. Because you have stuff where the eighth object is, you either have to move it out of the way, or you have to move all seven objects. Matlab, is telling you it would be faster if you were to tell it beforehand that you want to put 5 things in there, rather than just giving it things one by one, having to look for a new spot each time. You can do that by adding this line to the top of your code:
ant = [1:5];
There are also other ways to do this too.
Not sure if I got your problem right, but if you want to initialize an array of your self-defined class "TAnt", here is how I would do it
For TAnt's constructor method, put something like:
function obj = TAnt(source, target)
if nargin > 0
obj.mySource = source;
obj.myTarget = target;
else
obj.mySource = defaultValue;
obj.myTarget = defaultValue;
end
end
Then to initialize/pre allocate an array of default TAnt objects,
ants(1,n) = TAnt(); % n is the length of your ants array