When overriding equality operators in Lua (via the "__eq" metamethod), is there a way to still check for primitive equality (ie. not calling the overridden __eq, but checking if the two table values are referentially the same?) I need to do this from the C API, but I cannot find a suitable function there.
For example:
lua_newtable(L);
lua_newtable(L);
assert(!some_comparison());
lua_pushvalue(L,-1);
assert(some_comparison());
Where some_comparison() does not invoke the __eq metamethod.
(Please note lua_compare() does not satisfy this, in particular. I want a lua_rawcompare(), if you will - or rather a trick or workaround that will give me the equivalent. The idea is to prevent infinite recursion in a __eq implementation...)
If I understand your question correctly, I think you mean to use lua_rawequal:
int lua_rawequal (lua_State *L, int index1, int index2);
Returns 1 if the two values in indices index1 and index2 are
primitively equal (that is, without calling metamethods). Otherwise
returns 0. Also returns 0 if any of the indices are not valid.
Related
I was trying to implement vector algebra with generic algorithms and ended up playing with iterators. I have found two examples of not obvious and unexpected behaviour:
if I have pointer p to a struct (instance) with field fi, I can access the field as simply as p.fi (rather than p.*.fi)
if I have a "member" function fun(this: *Self) (where Self = #This()) and an instance s of the struct, I can call the function as simply as s.fun() (rather than (&s).fun())
My questions are:
is it documented (or in any way mentioned) somewhere? I've looked through both language reference and guide from ziglearn.org and didn't find anything
what is it that we observe in these examples? syntactic sugar for two particular cases or are there more general rules from which such behavior can be deduced?
are there more examples of weird pointers' behaviour?
For 1 and 2, you are correct. In Zig the dot works for both struct values and struct pointers transparently. Similarly, namespaced functions also do the right thing when invoked.
The only other similar behavior that I can think of is [] syntax used on arrays. You can use both directly on an array value and an array pointer interchangeably. This is somewhat equivalent to how the dot operates on structs.
const std = #import("std");
pub fn main() !void {
const arr = [_]u8{1,2,3};
const foo = &arr;
std.debug.print("{}", .{arr[2]});
std.debug.print("{}", .{foo[2]});
}
AFAIK these are the only three instances of this behavior. In all other cases if something asks for a pointer you have to explicitly provide it. Even when you pass an array to a function that accepts a slice, you will have to take the array's pointer explicitly.
The authoritative source of information is the language reference but checking it quickly, it doesn't seem to have a dedicated paragraph. Maybe there's some example that I missed though.
https://ziglang.org/documentation/0.8.0/
I first learned this syntax by going through the ziglings course, which is linked to on ziglang.org.
in exercise 43 (https://github.com/ratfactor/ziglings/blob/main/exercises/043_pointers5.zig)
// Note that you don't need to dereference the "pv" pointer to access
// the struct's fields:
//
// YES: pv.x
// NO: pv.*.x
//
// We can write functions that take pointer arguments:
//
// fn foo(v: *Vertex) void {
// v.x += 2;
// v.y += 3;
// v.z += 7;
// }
//
// And pass references to them:
//
// foo(&v1);
The ziglings course goes quite in-depth on a few language topics, so it's definitely work checking out if you're interested.
With regards to other syntax: as the previous answer mentioned, you don't need to dereference array pointers. I'm not sure about anything else (I thought function pointers worked the same, but I just ran some tests and they do not.)
I would like to understand how arguments are passed to function in .ll textual format.
My c function prototype looks like :
int power(int n, int r)
clang (followed by opt) compiles to :
define i32 #power(i32, i32) #0 {
"n" and "r" have vanished ! I need them here, in the textual IR!
Otherwise, it is not trivial to understand how the arguments are actually used.
Or maybe there is an obscure convention like "%1" is the first argument of the function, etc, but that does not seem so evident.
Any idea ?
Is there a naming convention or whatever to understand how my "c" arguments mapped to .ll names, in the function header ?
There's no such convention, no, and the names don't really map in that direction since IR has values rather than variables.
int a = 42;
while(b())
a += c();
d(a);
There is one variable called a, but the IR will probably contain four values that correspond to a's values at the end of the line 1, start of line 3, end of line 3 and start of line 4.
This answer shows how to add names. Whether to do that is up to you, and if you want to do it, you have to find a naming scheme too. "a.line4.column0" or anything else.
I have written a test utility function aequals (assert equals) that expects an actual result and an expected result as arguments. I use it like this:
aequals(fib(8), 21);
But now I have a function with multiple return values:
function stuff() return 1,2,3 end
I want to check its function by either checking it all together:
aequals( stuff(), {1,2,3} );
but this does not work because only "1" is left on the stack for aequals.
Or at least one after the other:
aequals( stuff()[1], 1 );
aequals( stuff()[2], 2 );
aequals( stuff()[3], 3 );
but this gives a syntax error, because stuff returns a tuple, not an array/table.
I tried to fix this using the array-constructor, which supposed to make a tuple into an array/table.
aequals( {stuff()}[1], 1 );
why this is a syntax error I can not understand.
I circumvented this by defining helper functions which I am sure are already in Lua, if I only knew where to look:
function arg0(a,b,c) return a end;
function arg1(a,b,c) return b end;
function arg2(a,b,c) return c end;
aequals( arg0(stuff()), 1 );
While this works it is quite cumbersome and it would be so much nicer to have the whole check in one line... but how?
function stuff() return 1,2,3 end
aequals( stuff(), {1,2,3} );
Used like this, the list returned by stuff() will be reduced to the first element, because stuff() is not the last expression in that expression list.
You could swap the table and stuff() to circumvent this in a simple manner.
aequals({1,2,3}, stuff())
Or use tables as suggested by Egor's comment.
From Lua 5.3 Reference Manual 3.4 Expressions
Both function calls and vararg expressions can result in multiple
values. If a function call is used as a statement (see ยง3.3.6), then
its return list is adjusted to zero elements, thus discarding all
returned values. If an expression is used as the last (or the only)
element of a list of expressions, then no adjustment is made (unless
the expression is enclosed in parentheses). In all other contexts, Lua
adjusts the result list to one element, either discarding all values
except the first one or adding a single nil if there are no values.
Can someone explain the following behavior? Specifically, why does the function return a different list every time? Why isn't some-list initialized to '(0 0 0) every time the function is called?
(defun foo ()
(let ((some-list '(0 0 0)))
(incf (car some-list))
some-list))
Output:
> (foo)
(1 0 0)
> (foo)
(2 0 0)
> (foo)
(3 0 0)
> (foo)
(4 0 0)
Thanks!
EDIT:
Also, what is the recommended way of implementing this function, assuming I want the function to output '(1 0 0) every time?
'(0 0 0) is a literal object, which is assumed to be a constant (albeit not protected from modification). So you're effectively modifying the same object every time. To create different objects at each function call use (list 0 0 0).
So unless you know, what you're doing, you should always use literal lists (like '(0 0 0)) only as constants.
On a side note, defining this function in the sbcl REPL you get the following warning:
caught WARNING:
Destructive function SB-KERNEL:%RPLACA called on constant data.
See also:
The ANSI Standard, Special Operator QUOTE
The ANSI Standard, Section 3.2.2.3
Which gives a good hint towards the problem at hand.
'(0 0 0) in code is literal data. Modifying this data has undefined behavior. Common Lisp implementations may not detect it at runtime (unless data is for example placed in some read-only memory space). But it can have undesirable effects.
you see that this data may be (and often is) shared across various invocations of the same function
one of the more subtle possible errors is this: Common Lisp has been defined with various optimizations which can be done by a compiler in mind. For example a compiler is allowed to reuse data:
Example:
(let ((a '(1 2 3))
(b '(1 2 3)))
(list a b))
In above code snippet the compiler may detect that the literal data of a and b is EQUAL. It may then have both variables point to the same literal data. Modifying it may work, but the change is visible from a and b.
Summary: Modification of literal data is a source of several subtle bugs. Avoid it if possible. Then you need to cons new data objects. Consing in general means the allocation of fresh, new data structures at runtime.
Wanted to write one myself, but I found a good one online:
CommonLisp has first class functions, i.e. functions are objects which
can be created at runtime, and passed as arguments to other functions.
--AlainPicard These first-class functions also have their own state, so they are functors. All Lisp functions are functors; there is no
separation between functions that are "just code" and "function
objects". The state takes the form of captured lexical variable
bindings. You don't need to use LAMBDA to capture bindings; a
top-level DEFUN can do it too: (let ((private-variable 42))
(defun foo ()
...))
The code in the place of ... sees private-variable in its lexical
scope. There is one instance of this variable associated with the one
and only function object that is globally tied to the symbol FOO; the
variable is captured at the time the DEFUN expression is evaluated.
This variable then acts something like a static variable in C. Or,
alternately, you can think of FOO as a "singleton" object with an
"instance variable".
--KazKylheku
Ref
http://c2.com/cgi/wiki?CommonLisp
Are the following two examples equivalent?
Example 1:
let x = String::new();
let y = &x[..];
Example 2:
let x = String::new();
let y = &*x;
Is one more efficient than the other or are they basically the same?
In the case of String and Vec, they do the same thing. In general, however, they aren't quite equivalent.
First, you have to understand Deref. This trait is implemented in cases where a type is logically "wrapping" some lower-level, simpler value. For example, all of the "smart pointer" types (Box, Rc, Arc) implement Deref to give you access to their contents.
It is also implemented for String and Vec: String "derefs" to the simpler str, Vec<T> derefs to the simpler [T].
Writing *s is just manually invoking Deref::deref to turn s into its "simpler form". It is almost always written &*s, however: although the Deref::deref signature says it returns a borrowed pointer (&Target), the compiler inserts a second automatic deref. This is so that, for example, { let x = Box::new(42i32); *x } results in an i32 rather than a &i32.
So &*s is really just shorthand for Deref::deref(&s).
s[..] is syntactic sugar for s.index(RangeFull), implemented by the Index trait. This means to slice the "whole range" of the thing being indexed; for both String and Vec, this gives you a slice of the entire contents. Again, the result is technically a borrowed pointer, but Rust auto-derefs this one as well, so it's also almost always written &s[..].
So what's the difference? Hold that thought; let's talk about Deref chaining.
To take a specific example, because you can view a String as a str, it would be really helpful to have all the methods available on strs automatically available on Strings as well. Rather than inheritance, Rust does this by Deref chaining.
The way it works is that when you ask for a particular method on a value, Rust first looks at the methods defined for that specific type. Let's say it doesn't find the method you asked for; before giving up, Rust will check for a Deref implementation. If it finds one, it invokes it and then tries again.
This means that when you call s.chars() where s is a String, what's actually happening is that you're calling s.deref().chars(), because String doesn't have a method called chars, but str does (scroll up to see that String only gets this method because it implements Deref<Target=str>).
Getting back to the original question, the difference between &*s and &s[..] is in what happens when s is not just String or Vec<T>. Let's take a few examples:
s: String; &*s: &str, &s[..]: &str.
s: &String: &*s: &String, &s[..]: &str.
s: Box<String>: &*s: &String, &s[..]: &str.
s: Box<Rc<&String>>: &*s: &Rc<&String>, &s[..]: &str.
&*s only ever peels away one layer of indirection. &s[..] peels away all of them. This is because none of Box, Rc, &, etc. implement the Index trait, so Deref chaining causes the call to s.index(RangeFull) to chain through all those intermediate layers.
Which one should you use? Whichever you want. Use &*s (or &**s, or &***s) if you want to control exactly how many layers of indirection you want to strip off. Use &s[..] if you want to strip them all off and just get at the innermost representation of the value.
Or, you can do what I do and use &*s because it reads left-to-right, whereas &s[..] reads left-to-right-to-left-again and that annoys me. :)
Addendum
There's the related concept of Deref coercions.
There's also DerefMut and IndexMut which do all of the above, but for &mut instead of &.
They are completely the same for String and Vec.
The [..] syntax results in a call to Index<RangeFull>::index() and it's not just sugar for [0..collection.len()]. The latter would introduce the cost of bound checking. Gladly this is not the case in Rust so they both are equally fast.
Relevant code:
index of String
deref of String
index of Vec (just returns self which triggers the deref coercion thus executes exactly the same code as just deref)
deref of Vec