lens icon indicating copy to clipboard operation
lens copied to clipboard

[WIP] Implements list-proper-lens and list-improper-lens

Open SuzanneSoy opened this issue 8 years ago • 9 comments

Here's an early draft of the improper list lens proposal discussed in https://github.com/jackfirth/lens/issues/292 . The two lenses implemented are:

(lens-view list-proper-lens (list* 1 2 3 4)) ;; => (list 1 2 3 4)
(lens-view list-improper-lens (list 1 2 3 4)) ;; => (list* 1 2 3 4)

Roughly, an improper list which was constructed using list* can be turned into the list which would be obtained by passing list the same arguments, and vice versa.

If this sounds okay, I'll add documentation, as well as stx-proper-lens (which turns an improper syntax list into a proper syntax list), and stx-improper-lens (which turns a proper syntax list into an improper one). Other syntax manipulations operating on improper syntax lists can then be obtained with simple combinations, e.g.

(define stx-improper->list-lens (lens-compose stx->list-lens stx-proper-lens))
…

@jackfirth I didn't check in-depth the requirements for isomorphisms, but since (compose list-proper-lens list-improper-lens) = identity and (compose list-improper-lens list-proper-lens) = identity for all valid inputs (unless I missed a corner case), doesn't that make the pair of lenses an isomorphism? (In which case I guess I should rename them to list->list*-lens and list*->list-lens, or proper->improper-lens and improper->proper-lens, or something similar).

SuzanneSoy avatar Jan 05 '17 22:01 SuzanneSoy

Coverage Status

Coverage increased (+0.03%) to 98.955% when pulling c7cdca6876407fe68990b36b5b22c60c79b9a2fc on jsmaniac:improper-list+stx into 85b147080bf93b52f7b431777da83470c3135992 on jackfirth:master.

coveralls avatar Jan 05 '17 22:01 coveralls

Calling it stx-improper-lens would be wrong. The word "improper" should not be separated from the word "list." The words "improper syntax" could mean a lot of things other than an improper list wrapped in a syntax object.

AlexKnauth avatar Jan 05 '17 23:01 AlexKnauth

@AlexKnauth Right. improper-stx-list-lens then?

I'm not terribly fond of list-proper-lens and list-improper-lens, as it sounds like the lens itself is an (im)proper lens (it's a proper lens in both cases, thanks to the contract), I'd rather call them (im)proper-list-lens, if that's okay with @jackfirth (or use one of the a->b names I mentioned, if it's an isomorphism).

SuzanneSoy avatar Jan 05 '17 23:01 SuzanneSoy

Names in a->b format can still make sense for lenses that aren't isomorphisms; think of stx->list-lens.

AlexKnauth avatar Jan 06 '17 00:01 AlexKnauth

The error message "expected an improper list of length n (plus the last element)" isn't clear enough. Would something to the effect of "length n (including the tail element)" be less ambiguous?

AlexKnauth avatar Jan 06 '17 00:01 AlexKnauth

In the setter you have to refer to the old target to do the length check; I think that disqualifies it from being an isomorphism; I'm not sure.

AlexKnauth avatar Jan 06 '17 00:01 AlexKnauth

including the tail element ⇒ Agreed Re. isomorphism, you're probably right, I thought round-tripping would be enough, but I see now how the length check can be a problem.

SuzanneSoy avatar Jan 06 '17 00:01 SuzanneSoy

If you can't make them out of make-isomorphism-lens they're definitely not isomorphisms. In this case, the reason is that the lenses don't convert between proper and imporper lists - they take a list that could be proper or improper and view it as one or the other. The target could be any list, proper or otherwise, and the view is "normalized" to either proper or improper. So I'm not really a fan of list->list* and list*->list names. I think something like list->proper-list and list->improper-list would be better, as they explicitly state that the target is any list and the view is normalized.

jackfirth avatar Jan 06 '17 03:01 jackfirth

Hmmm, thinking about this more.... what if we threw out the element-replacement part of these lenses? Instead, we had a lens that viewed true or false based on whether the list is improper:

> (lens-view list-improper?-lens (list 1 2 3))
#f
> (lens-view list-improper?-lens (list 1 2 . 3))
#t
> (lens-set list-improper?-lens (list 1 2 3) #t)
(list 1 2 . 3)

This still has the problem of lists where the last element is a list:

> (lens-set list-improper?-lens (list 1 2 (list 3)) #t)
(list 1 2 3)

I'm really not sure how to resolve this issue; there seems to be inherent ambiguity in the problem domain.

jackfirth avatar Jan 06 '17 03:01 jackfirth