# An analog to Common Lisp EQL specialization?

**URL:** <https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380>\
**Category:** General Usage\
**Tags:** dispatch\
**Created:** [May 2, 2022, 6:01pm UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380 "2022-05-02T18:01:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [May 2, 2022, 6:01pm UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/1 "2022-05-02T18:01:44Z")

</div>

The Essentials section of the Julia documentation suggests that methods can be specalied on `Val` types. Perhaps I’m misunderstanding, but this seems analogous to Common Lisp’s EQL specialization.

Assuming that’s the case, I’m trying to use `Val` types to specialize the second `property` argument of`Base.getproperty`, rather than a conditional tree.

```julia
struct MyStruct
    a::Int
end

function Base.getproperty(o::MyStruct, prop::Val{:b})
    o.a * 2
end

ms = MyStruct(3)
MyStruct(3)

ms.a
3

methods(Base.getproperty, [typeof(ms), Val{:b}])
# 1 method for generic function "getproperty":
[1] getproperty(o::MyStruct, prop::Val{:b}) in Main at none:1

Base.getproperty(ms, :a)
3
Base.getproperty(ms, :b)
ERROR: type MyStruct has no field b
Stacktrace:
 [1] getproperty(x::MyStruct, f::Symbol)
   @ Base .\Base.jl:33
 [2] top-level scope
   @ none:1

```

So, what am I doing wrong?

This works though:

```julia
Base.getproperty(ms, Val{:b}())
6

```

I guess I don’t understand the point of `Val`, because I’d have expected

```julia
:b isa Val{:b}
false

```

to be `true`, not `false`.

Does Julia have something analogous to Common Lisp EQL specialization?

---

<div class="post-metadata">

**Author:** ![zweiglimmergneis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zweiglimmergneis/32/7892_2.png) [@zweiglimmergneis](https://discourse.julialang.org/u/zweiglimmergneis)\
**Post date:** [May 2, 2022, 9:14pm UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/2 "2022-05-02T21:14:02Z")

</div>

Unfortunately I’m not familiar with Common Lisp EQL specialization. But the behaviour of Julia here is the following. You get the error, because you call the original version of `getproperty`. To call your definition, the second parameter needs to be of type `Val{:b}` (equivalent to your second call).

```julia
julia> getproperty(ms, Val(:b))
6
# because
julia> typeof(Val(:b))
Val{:b}

```

`:b` is of type `Symbol`. [Docs](https://docs.julialang.org/en/v1/base/base/#Base.Val)

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [May 3, 2022, 7:40am UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/3 "2022-05-03T07:40:05Z")

</div>

> [@Mark\_Nahabedian](#):
>
> I’m trying to use `Val` types to specialize the second `property` argument of `Base.getproperty` , rather than a conditional tree.

Something like this should work. It is very close to your original code, where the only missing piece was to handle the “conversion” from `Symbol` _values_ (that the `obj.prop` syntax produces) to `Val` _types_ (that you want to use for the dispatch in order to avoid a conditional tree).

```julia
struct MyStruct
    a::Int
end

# Forward `o.propname` to `getproperty(o, Val(:propname))`
#
# Rely on constant propagation to statically know about the type of `Val(prop)`
# when the value of `prop` is statically known
Base.getproperty(o::MyStruct, prop::Symbol) = getproperty(o, Val(prop))

# Default implementation: assume prop refers to a "real" field and call `getfield`
Base.getproperty(o::MyStruct, prop::Val{T}) where {T} = getfield(o, T)

# Specific methods defining new properties
# This is where dispatch avoids having a conditional tree
Base.getproperty(o::MyStruct, prop::Val{:b}) = o.a * 2
Base.getproperty(o::MyStruct, prop::Val{:c}) = o.a * 3.0

```

```julia
julia> ms = MyStruct(3)
MyStruct(3)

julia> ms.a
3

julia> ms.b
6

julia> ms.c
9.0

```

Overall, this should be optimized away by the compiler, provided that constant propagation (of the property names) can happen:

```julia
julia> b(o::MyStruct) = o.b
b (generic function with 1 method)

julia> @code_native b(ms)
        .text
        movq (%rdi), %rax
        addq %rax, %rax
        retq
        nopw (%rax,%rax)

```

---

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [May 3, 2022, 10:43am UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/4 "2022-05-03T10:43:12Z")

</div>

Thanks for the solution, I was looking for something like this myself. However there is a question still hanging

Is this more performant than the usual `if...else` structure? 🧐

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [May 3, 2022, 11:15am UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/5 "2022-05-03T11:15:23Z")

</div>

> [@nandoconde](#):
>
> Is this more performant than the usual `if...else` structure?

I would think both solutions have the same performance in most cases, since IIUC both implementations rely heavily on optimizations that are enabled by constant propagation.

Expanding on the previous example, we see that the code generated for the `b` property is exactly the same for a conditional tree that what we had above (again, provided that we’re in a context where constant propagation can happen):

```julia
struct MyStruct2
    a :: Int
end

function Base.getproperty(o::MyStruct2, prop::Symbol)
    if prop == :b
        o.a * 2
    elseif prop == :c
        o.a * 3.0
    else
        getfield(o, prop)
    end
end

```

```julia
julia> ms = MyStruct2(3, 4.0)
MyStruct2(3, 4.0)

julia> b(o::MyStruct2) = o.b
b (generic function with 1 method)

julia> @code_native b(ms)
        .text
        movq (%rdi), %rax
        addq %rax, %rax
        retq
        nopw (%rax,%rax)

```

---

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [May 3, 2022, 7:23pm UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/6 "2022-05-03T19:23:54Z")

</div>

CommonLisp doesn’t have a notion of properties, but for what I’m trying to do, the code would look something line (I’ve not programme3d in CL in about a decade and don’t have a lisp installed on this computer, so excude any errors):

```julia
(defclass my-struct ()
  ((a :initarg :a :reader ms-a)))

(setq ms (make-instance 'my-struct :a 3))

(defmethod get-property((object my-struct) (property (eql :b)))
  (* (ms-a object) 2))

(get-property ms :b)
;;; would return 6

```

---

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [May 3, 2022, 7:25pm UTC](https://discourse.julialang.org/t/an-analog-to-common-lisp-eql-specialization/80380/7 "2022-05-03T19:25:02Z")

</div>

Thanks for the solution.

I guess I don’t understand the point of `Val` and why this method is needed. I guess so long as the property is known at compile time the access would get in-lined.

If anyone wants to use `Val` specialization for `getproperty`, I’ve added some support for it in [GitHub - MarkNahabedian/NahaJuliaLib.jl: Some utility functions for Julia programming.](https://github.com/MarkNahabedian/NahaJuliaLib.jl). In particular,

```julia
@njl_getprop MyStruct

```

will define the three methods needed so that `getproperty` and `propertynames` will work for `Val` specialized `getproperty` methods. For any comments or suggestions, feel free to open an issue for that repository or comment on this thread.

Thanks.
