I have two types A and B. I have written B(a::A) and convert(::Type{B}, a), but this does not immediately make Array{B}(as::Array{A}) work. Must I write this method as well? According to
the documentation, I would expect Julia would handle the rest for me.
struct A end
struct B end
B(a::A) = B();
convert(::Type{B}, a) = B(a);
# These work
B(A());
convert(B, A());
# This doesn't
Array{B}([A()]);
This is the error
ERROR: LoadError: MethodError: Cannot `convert` an object of type A to an object of type B
Closest candidates are:
convert(::Type{T}, !Matched::T) where T at essentials.jl:154
B(::A) at /home/mvarble/test.jl:3
Stacktrace:
[1] setindex!(::Array{B,1}, ::A, ::Int64) at ./array.jl:767
[2] copyto! at ./abstractarray.jl:753 [inlined]
[3] copyto! at ./abstractarray.jl:745 [inlined]
[4] Type at ./array.jl:482 [inlined]
[5] Array{B,N} where N(::Array{A,1}) at ./boot.jl:427
[6] top-level scope at none:0
[7] include at ./boot.jl:326 [inlined]
[8] include_relative(::Module, ::String) at ./loading.jl:1038
[9] include(::Module, ::String) at ./sysimg.jl:29
[10] exec_options(::Base.JLOptions) at ./client.jl:267
[11] _start() at ./client.jl:436
You have to add a method to convert from Base, and not define a new convert function in the current module. Therefore you should write:
Base.convert(::Type{B}, a) = B(a)
or
import Base: convert
before defining convert as you did in your code.
Related
I was following along this notebook (originally written in Julia 0.x, I am using Julia 1.7.1). One of the cells defines the following macro.
macro twice(ex)
quote
$ex
$ex
end
end
On the very next cell, this macro is invoked.
x = 0
#twice println(x += 1)
Replicating this in the REPL (for brevity) results in the following error.
ERROR: syntax: invalid assignment location "Main.x" around REPL[1]:3
Stacktrace:
[1] top-level scope
# REPL[4]:1
So, I understand that x += 1 is somehow causing this problem, but after going through the docs (metaprogramming), I could not figure out why exactly this is an invalid assignment or how to fix this.
#macroexpand #twice println(x += 1) successfully returns the following.
quote
#= REPL[1]:3 =#
Main.println(Main.x += 1)
#= REPL[1]:4 =#
Main.println(Main.x += 1)
end
So, I tried evaling this in the top-level without the Main.s, and it evaluates successfully.
x = 0
eval(quote
println(x += 1)
println(x += 1)
end)
Output:
1
2
But, if I add the module name explicitly, it throws a different error.
eval(quote
Main.println(Main.x += 1)
Main.println(Main.x += 1)
end)
ERROR: cannot assign variables in other modules
Stacktrace:
[1] setproperty!(x::Module, f::Symbol, v::Int64)
# Base ./Base.jl:36
[2] top-level scope
# REPL[14]:3
[3] eval
# ./boot.jl:373 [inlined]
[4] eval(x::Expr)
# Base.MainInclude ./client.jl:453
[5] top-level scope
# REPL[14]:1
I tried a few other things, but these are the only things that I think might be getting somewhere.
Why exactly is the assignment in the first macro code block invalid? Is it for the same reason that evaling in the top-level with the module Main specified fails?
How can this invalid assignment be circumvented, OR how do I port this to Julia 1.7?
Use esc (This "prevents the macro hygiene pass from turning embedded variables into gensym variables"):
julia> macro twice(ex)
esc(quote
$ex
$ex
end)
end;
julia> x=1
1
julia> #twice println(x += 1)
2
3
I am very new in Julia, so maybe it is stupid question. I have the following code:
a = [1.0, 2.0];
b = [2.2, 3.1];
Int(a.>b)
It gives me an error:
MethodError: Cannot `convert` an object of type BitArray{1} to an object of type Int64
This may have arisen from a call to the constructor Int64(...),
since type constructors fall back to convert methods.
Stacktrace:
[1] Int64(::BitArray{1}) at ./sysimg.jl:77
[2] include_string(::String, ::String) at ./loading.jl:522
The command 1(a.>b) works well.
Could You explain me:
Why my implicit conversion did not work?
a.>b is of type BitArray{1}. With Int(a.>b) you are trying to convert an array, namely a BitArray, to a single integer, which doesn't make sense.
Instead you probably want to convert the elements of the array to integers:
julia> a = [1.0, 2.0];
julia> b = [2.2, 3.1];
julia> Int.(a.>b)
2-element Array{Int64,1}:
0
0
Note the dot in Int.(a.>b) which broadcasts the conversion to every element.
The reason why 1(a.>b) works is because it is being translated to 1*(a.>b). This is a multiplication of a number and an array which is an element-wise operation.
Is it possible to add element to cell array including case when it is currently empty and or not exist?
All of these methods work
>> C={12}
C =
[12]
>> C=[C;13]
C =
[12]
[13]
>> C{end+1}=14
C =
[12]
[13]
[14]
But all of them require C exists.
Neither work if C does not exist. Is it possible to do so?
I have two cell arrays.
A(290*6) and B(300*6);
First column in two arrays are identical. I compared first column of two cell arrays using 'ismember'. I want to do that ; where cell elements are missing in cell array(A), I have to add a row where element is missing. Is it possible in Matlab?
It's not easy to insert rows into an existing matrix or cell array; it's easier to construct a new one and fill it appropriately.
Find the locations of the contents of the first column of A in the cell array B:
[aa,bb] = ismember([A{:,1}],[B{:,1}]);
Create a new empty cell array:
C = cell(length(B),size(A,2))
Fill it:
C(:,1)=B(:,1)
C(bb,2:end) = A(aa,2:end);
For example, given this A ("3" row missing)
[1] [3]
[2] [5]
[4] [3]
And this B:
[1]
[2]
[3]
[4]
This returns:
[1] [3]
[2] [5]
[3] []
[4] [3]
To fill the empty spaces with the previous row (this will only work if the empty rows are non-consecutive and the first row of C is non-empty):
n = setdiff(1:length(C),bb)
C(n,2:end) = C(n-1,2:end);
I think you can directly use the second output of setdiff
[d,i] = setdiff(B(:,1),A(:,1))
i will tell you where the rows in A are that are missing.
From playing with B, I see that a B::LOGOP object (call it "$op") referring to either a && or and operator will both return "and" upon calling $op->name. Is it possible to determine which operator the LOGOP refers to merely by examining $op?
I am not expert for perl internals, but LOGOP refers to logical operator group. So I don't think you can know individual operator without examining the name. Even B::Terse displays it:
perl -MO=Terse -e '$a && $b'
Shows:
....
LOGOP (0x198ad94) and
UNOP (0x198adec) null [15]
PADOP (0x198ae08) gvsv GV (0x187bb9c) *a
UNOP (0x198adb4) null [15]
PADOP (0x198add0) gvsv GV (0x187bc9c) *b