# @enum multiplication

Is this the best way to do this?

``````@enum BuySell (Buy=1; Sell=-1)

import Base.*
*(x::BuySell,  y::Any    )  = Int(x)   * y
*(y::Any,      x::BuySell)  = y        * Int(x)

Sell * 10    #  = -10
``````

So I can put * Buy or * Sell in any equation.

Not trying to be facetious here, but why not

``````julia> Sell = -1
-1

julia> Sell * 10
-10
``````

(Iâ€™ve never really understood what enums are for, so Iâ€™m probably missing something here!)

Iâ€™m setting up deal structures like this

``````@enum BuySell Buy Sell
@enum CCY AUD USD GBP EUR CAD NZD CHF

struct SomeDeal
Currency::CCY
Notional::Float64
end
``````

I figured using enums for field types (instead of strings or symbols) would give

• less memory
• faster lookups
• clarity (knowing exactly what values a field can take)

If this is wrong or thereâ€™s a better way to do it please let me know.

In a relational database, BuySell and CCY would be primary keys for their respective tables.
The BuySell and CCY fields within the Deals table would have their values restricted via PK-FK relationships to these other tables.

In Julia Iâ€™m working with DataFrames and Arrays of defined structures (e.g. SomeDeal).
Iâ€™d like to have similar PK-FK relationships between structures.

enums is the best I can think of

This enum package supports arithmetic

CEnum.jl

For adding arithmetic yourself, I think your approach is probably correct (or mostly). It is type piracy. But, if you are not making a package to release for general use, thatâ€™s ok.

I wrote a package (unregistered) MEnums.jl that allows you to mutate, that is add more items, to an existing enum. It is a new type. I did not support arithmetic. I donâ€™t know how often arithmetic is needed. I am starting to think adding it to MEnums.jl is a good idea. You might also like the extensibility for your application.

I wrote MEnums.jl with the idea of using them in a situation where you are tempted to make a lot of types and iterate over a heterogeneous array, dispatching on them. This is not efficient. But, I havenâ€™t yet explored this further. My motivations were somewhat related to yours.

For the most part, I copied code from the `Enum` in `Base`.

1 Like

CEnum.jl seems to work for +, - but not *

If it worked for * it would be the best solution. Thank you

My mistake. I saw that they import `*` from `Base`, which is why I thought it was supported. But, in fact, although itâ€™s imported, they never use it.

1 Like

also, do you know of any package that automatically maps a string or symbol to the corresponding enum?

e.g. `"Buy"` or `:Buy` to enum `Buy`.

Iâ€™ve been using `instances()` to create dictionaries to map Symbols to enums.
It would be nice to have a function to do it automatically.

``````julia> @enum Color red blue green;

julia> csym = :red;

julia> eval(csym)
red::Color = 0
``````

But this is slow: 45ns on my machine. Iâ€™m guessing that the fact that you want to do multiplication with the enum instances and also access them via strings or symbols means that there is a better design to get what you want. Maybe without enums.

This works

``````struct Buy end
struct Sell end

struct deal
N::Int64
end

d = deal(10,Sell())

julia> Position_Value(d)
-10
``````

But Iâ€™d really like to do something like this.

``````Buy_Sell = Union{Buy => +, Sell => -}
deal(10,Sell)
``````

I donâ€™t know of any other way to restrict the possible values a field can take. @enum restricts to labelled numbers, Union restricts to a set of types. Is there any way (as above) to restrict to labelled operators ?

I suppose enums in Base Julia, and all the packages take 1 byte (and in C always?). Primitive types in Julia are a minimum 8 bits (and then multiples of 8), e.g. `primitive type Bool <: Integer 8 end`.

It was decided to not bring bitfields over from C/C++, to not have the language too complex, but the above limitation could be relaxed someday, to allow 1-bit `Bool`s. Bitfields ARE provided here (even â€śfully supports insane Câ€ť), for C interop, but Iâ€™m not sure if this package is useful for just using in Julia without C interop:

Iâ€™m just showing more compressed is possible, as with:

I suppose it would be great if your example, as is (or with different Notational), could simply be more compressed:

``````struct SomeDeal
Currency::CCY  # could in theory take 1 bit, and combine with the next field, thus those too taking 1 byte:
Buy_Sell::BuySell # actually in your case only needs 3 bits, 7 should be plenty, are there more than 128 currencies (in total, not just popular), not counting ALL crypto...? They are in the thousands...
Notional::Dec32  # Maybe Float16, or Dec64?
end
``````

You could encode that struct in 5 bytes not 6 (or your original 10), with a hack in 3 (less precision, different type), or a maybe 4.

Julia does consider each field in the struct separately, and thus must expand each to the minimum 8 bits, but applying a macro to the whole struct could change that assumption without changing the core language (also if primitive changed in the language).

PostgreSQL has Float32 (there â€śrealâ€ť; only 6 decimal digits precision) and Float64, no Float16, and the â€śdecimalâ€ť type which is variable length, I suppose 3 or 4 bytes for the length alone (as for text strings), but at least in RAM in Julia you could get to 2 bytes with Float16.

This only supports Dec32 as smallest (same as the standard), supporting â€ś7 decimal digitsâ€ť, but you do not seem to care about good (decimal) precision, maybe Float16 would work for you, and if you premultiply by 1000 then I think you 3 correct decimal digits.

Alternatively if you choose to go with Float32 you could steal lowest 3+ bits you need from the Significand (and maybe even steal the sign bitâ€¦). I would have to look into it, but stealing bits from Dec32 might be dangerous (because of its different (refined)
Chenâ€“Ho encoding).

1 Like

Many interesting points. Thank you