Yeah, I might have called it 'coercify if not for the confusion it would cause. ;) And so far I only have one (niche) use in mind for it, so it doesn't have to be nice and brief.
Actually, it would make more sense to call it "transformify." Both "coerce" and "convert" have the connotation of at least sometimes transforming from one kind of value to another. For my purposes, the function [+ 20 _] is a valid behavior--it certainly makes sense to 'copy a data structure but add 20 to one of its parts--and yet the inputs and outputs of that transformation are of the same kind.
---
may be a case where the primitives themselves need multiple coercions.
Nah, you can resort to (as test x) and (as conversion x), with 'test and 'conversion--or 'transform--being callable types.
This is the same thing I meant when I said "you can make a 'test type to turn 'testify into a coercion."
---
I want to try really hard to have just one coercion per type combination, and let users create new types when they want a different conversion. You point out that's verbose, but it may not be overly so, and at least it's overrideable.
Feels like I'm talking past you a bit.
When users want different conversions, they can already define new "anything -> type-foo" global functions, and those are already extensible/overrideable. There's no need to add a framework for that, even if it does manage to be a tolerably simple framework with a tolerably brief API.
Code that chooses between the super-similar testify.x and checkify.x is just as doomed to being arbitrary and hardcoded as if it were to choose between (as test x) and (as check x). The 'coerce framework doesn't help with this hardcoding issue.
---
And I'd definitely try to designate one of them the 'default' coercion like arc already does.
I don't generally agree with designating one operation as default simply based on the types it manages, like "anything -> type-foo." For a more obvious example, it would be especially silly to identify a default "number x number -> number" operation.
Still, I think we agree on what's important. If the point of operation X is to reshape things to expose their fooish quality, then we don't want an operation Y whose point is also to reshape things to expose their fooish quality.
You draw the line farther toward "reshape things to expose their _____ish quality" and embrace 'coerce as a way to abstract the _____ away. As for me, I suppose I've come to believe _____ is an intrinsically subjective, second-class concept.
At one point I wanted Penknife to have a type type, with operations like list'ish.x, list'ify.x, [inherits list seq], and [new.list a b c], which could then be abstracted into other utilities like [def list my-list a b c]. It's been a while, and now I've kinda given up looking for a great advantage; I think the one plus would be having only a single global variable to attach the list documentation to, and I'm not especially excited about that. ^_^
These days I have the vague notion that a user-defined type which extends all the right things oughta be an equally pure representation of _____ish quality; the correspondence between _____s and types isn't one-to-one.
"You draw the line farther toward "reshape things to expose their _____ish quality" and embrace 'coerce as a way to abstract the _____ away. As for me, I suppose I've come to believe _____ is an intrinsically subjective, second-class concept."
That's a pretty good summary. I really haven't considered that alternative at all, so keep me posted on how it goes :)
Lol, by "second-class concept", I mean something that isn't modeled as a value in the language. My gut reaction is that it takes zero work to pursue that alternative. :-p
But yeah, I do still need to solve the same problems 'coerce solves. My alternative, if it isn't obvious by now, is to have global functions that do (fooify x) and occasionally (transform-as-foo x (fn (fooish-x) fooish-result)).
coerce, ify, transform, these seem really similar to me. Why bother splitting such hairs?
I'm reminded of your earlier statement: The purpose of a coercion isn't entirely explained by "I want something of type X." In these cases, it's "I want a Y of type X," and the Y is what's different. Perhaps you didn't go far enough? If you're going to eschew coerce why not get rid of all trace of the types? Don't call it stringify. Call it serialize. Don't call it transform-to-int, call it parse-number. Don't call it aslist, call it scan. Or something like that. It isn't these names, but good name choices would bring me entirely in your camp :)
Ah, right. ^_^ Yeah, most of the times I "use" these things, I'm just making some other abstract nonsense utility. It could be a while until I have another down-to-earth application to try this stuff on.
coerce, ify, transform, these seem really similar to me.
Well, I don't distinguish "ify" from "coerce" except when it helps tell apart the subtle variants we're talking about in this conversation. :-p The subtle variants wouldn't all go into the same language, I hope.
"Transform," on the other hand, seems more general. Really, 'transform as a type wouldn't mean anything other than "unary function, preferably pure." I could very well be splitting hairs by drawing a distinction between that context and the everyday "function" context. However, I think there are some things I want to treat differently between those cases, like ints (multiplication in function position, constant functions in transform position).
If you're going to eschew coerce why not get rid of all trace of the types?
Actually, that's how I think about it. Coercion is a technique to focus output ranges or widen input ranges so utilities are easier to use. If I consistently want a certain kind of focusing--and only then--I'll put it into a utility.
I name those utilities to correspond not with specific types but with informal target sets, usually based on the extensible utilities they support. However, any given tagged type means little except the extensions associated with it, so I think my approach has a natural tendency toward corresponding names anyway.
Don't call it [this], call it [that].
I think I agree with you there. However, I don't expect to come up with witty names as fast as I change my mind about the designs of things. :) For now I'm happy resorting to cookie-cutter names like 'fooify, 'fooish, and 't-foo, just so it's easier to notice relationships between variables and between informal concepts.
"Coercion is a technique to focus output ranges or widen input ranges.."
That's a nice way to think about it.
"I don't expect to come up with witty names as fast as I change my mind about the designs of things. :) For now I'm happy resorting to cookie-cutter names like 'fooify, 'fooish, and 't-foo"