-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not use nothing for holes? #2
Comments
I think it's a good idea to consider using a singleton other than But whichever value is chosen, there should always be a way to escape it. We can escape it with |
You are right an escape mechanism is good to have either way. However, I expect |
Why not do this at the macro level? |
@tkf do you propose to keep |
Yeah, I think that's the most robust solution. For example, if you have mapobjects(f, m::Module) = (f(getfield(m, n)) for n in names(m)) and use f(x) = count(bind(isa, x, ◻), [Integer, Symbol]) could break it. |
Maybe I don't fully get the example. I do see that it has possibly surprising behavior. But the same is true with I also with |
I think it's more about g(x) = count(bind(isa, Some(x), nothing), [Integer, Symbol]) instead then the first argument of |
@goretkin suggested |
I thought the point of Sometimes there is no easy way to avoid "sentinel" values/types like |
No, I think the point of The point of hole is that you can write instead of |
That's what I meant. |
I think we're discussing two separate issues, then.
If you do not use a macro, then you can never safely do If you use a macro, then you can use I don't understand what @tkf is illustrating in #2 (comment) , however, and why lowering or I don't see a privileged choice of sentinel, except if for convention that |
I never tried to argue this. My main claim has been that "it's more about
|
I agree with all of that. I was responding perhaps to ”Yeah, I think that's
the most robust solution. For example, ...”.
…On Fri, Jun 26, 2020, 9:50 PM Takafumi Arakaki ***@***.***> wrote:
why nothing is more robust than hole
I never tried to argue this. My main claim has been that "it's more about
Some{T}-vs-T than nothing-vs-hole."
I don't see a privileged choice of sentinel, except if for convention that
Some probably exists to escape nothing, so it seems like nothing is a
good choice to stick with.
Union{Nothing,Some{T}} is the canonical optional value in Julia. This
"convention" is important because you get a common set of tools to work
with this type (e.g., something). Or maybe in the future we'll get f?(x)
to automatically lift f(::T) to Union{Nothing,Some{T}}. These things are
important when you want to build arguments for bind programmatically.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEN3M5JH55PQCGVRAEJ37DRYVF77ANCNFSM4OAVN2JQ>
.
|
I see. Yes, that part sounds like To sum-up, my arguments are:
|
@jw3126 do you think this is okay to close? |
I would prefer to keep it open. I am still favoring hole. I do prefer fumctions over macros and with hole using the fix function is much less dangerous. Also
|
I agree it's less dangerous, but the danger is present regardless of the choice of sentinel values. It seems like good practice would always require So given that thinking, I agree with @tkf that it's worth using the "canonical optional value" representation. To elaborate............. The opposite choice is to escape string literals. That's what e.g. https://github.com/jkrumbiegel/ReadableRegex.jl allows you to do, in addition to giving descriptive names for all the regex operators. I think to write safe, modular code, you can't assume the absence of a sentinel value if the value is coming from another module, that you'd like to not really know much about. So the only way to do that in the realm of Julia values is to ensure that anything that could take on a sentinel value but not mean a sentinel value be wrapped in something that adds a layer of "This value does not have the meaning of a sentinel value". Many uses of this package probably don't have values coming from other modules. The fixed (/ bound) values are literals in the code. In that case it feels very safe to get away without writing But in the spirit of having both convenience and orthogonality (so you can replace a literal by a variable reference, and now there's a risk one day it will=== sentinel value), you now cannot avoid using a macro. Using a macro lets you be concise and safe, otherwise you have to escape a lot of stuff with And so then since you're using a macro anyway, then why not choose the pattern that Julia uses elsewhere, so that we do not need to invent yet another "escaping scheme"? And the only way We could just say "when you're doing this weird thing of That was much longer elaboration than I intended, but that's how I would defend the choice to use
I think that is a good feature, and I don't exactly see what's less natural about using Also, by the way, we could borrow from https://github.com/FluxML/MacroTools.jl/blob/e43325c939cfe7bbb02900a9695309af4d14d1a2/docs/src/pattern-matching.md#L55
|
I think you should definitely define your own singleton for this package to use rather than one from Base. While no sentinel value is safe, using your own homemade sentinal value is way safer than one from Base.
I think it's really nice that this package doesn't need a macro to have nice syntax. I'd rather something like this just took advantage of multiple dispatch. |
You don't need to use any sentinel if you store |
@MasonProtter if you can provide examples of other packages, or Base defining singletons that serve as sentinels, I think it would help the discussion. |
Doesn't the user then have to write
I'm not sure I understand what you're asking for. Are you just asking about examples of packages that define singletons for directing dispatch? |
@MasonProtter I don't think it's a good approach to sacrifice robustness just for convenience. IMHO it's very important to get a rigorous API first and then think about the syntax sugar. Using
@goretkin Actually, https://github.com/JuliaFolds/InitialValues.jl (e.g., |
If you're using a macro for the surface syntax, why do you need |
I think it is reasonable to argue that all of these can use a mechanism other than |
I think @tkf answered the question, but perhaps @MasonProtter has a different implementation in mind. If so, could you show what you mean in terms of how would you directly construct the
This might be a pedantic point, and I may be wrong about it, but I was considering the value e.g. julia> FixArgs.fix(print, nothing, Some(:a))(:b)
ba
julia> FixArgs.fix(print, nothing, :a)(:b)
ba You can escape julia> FixArgs.fix(print, nothing, Some(nothing))(:b)
bnothing And you can also escape a julia> FixArgs.fix(print, nothing, Some(Some(:a)))(:b)
bSome(:a) One design change that we could make is to make |
I don't have a strong opinion on this but I think it's OK to "cast" But I think that it's better to normalize the representation when constructing |
I've played around with using a type to index into the positional arguments of a function, instead of just using Lines 139 to 140 in 3572230
If that solution pans out, then indeed the idea will not use |
I've taken this idea pretty far, and effectively "holes" are not represented with |
Instead of using
nothing
to indicate holes, we could useSo we don't have to think about escaping
Some(nothing)
and also have more cute notation like:@bind ◻ == 1
The text was updated successfully, but these errors were encountered: