common-lisp中更好的pythonic`join` [英] Nicer pythonic `join` in common-lisp

查看:123
本文介绍了common-lisp中更好的pythonic`join`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Edi Weitz的cl食谱中,对于pythonic join,建议使用以下功能:

In Edi Weitz's cl cookbook, for the pythonic join, this function is suggested:

(defun join (separator list)
  (with-output-to-string (out)
    (loop for (element . more) on list
          do (princ element out)
          when more
            do (princ separator out))))

但是,我以某种方式思考,必须有一种以另一种方式表达join的方法,也许使用format的功能...

However, somehow I was thinking, there must be a way to express join in another way, maybe using format's capabilities ...

在Seibel的书中(在关于format的章节中),我们发现列表中的字符串通过分隔符连接到单个字符串 ", "通过:

In Seibel's book, (in the chapter about format) we find joining of strings in a list to a single string with the separator ", " by:

(defvar l '("a" "b" "c"))

(format nil "~{~A~^, ~}" l)
;; "a, b, c"

这是一个pythonic联接,非常简洁; ~^指令使", "仅在最后一个元素之前添加,而在后面没有元素时不添加.

Which is a pythonic join and which is very terse; the ~^ directive makes that ", " is added only until just before the last element and not added when no element is following.

但是,这里的分隔符字符串", "是format指令的一部分.

However, here, the separator string ", " is part of the format directive.

一个棘手的案例是(defvar sep #\Tab). 如果sep "#\Tab"的表示形式可以在此format指令的中间放置为分隔符,则会导致:

A tricky case is e.g. (defvar sep #\Tab). If the representation of sep "#\Tab" literally can be placed as a separator in midst of this format directive, resulting in:

(format nil "~{~A~^#\Tab~}" l)

我们会达到目标的.

很显然,必须使用宏来生成format指令... 我尝试了类似(princ-to-string sep)的方法,但这给出了"#\\Tab"而不是"#\Tab".

Obviously, one has to use a macro to generate the format directive ... I tried things like (princ-to-string sep) but this gives "#\\Tab" and not "#\Tab".

例如

(defmacro join (sep l)
  `(format nil ,(format nil "~{~A~}" `("\~\{\~A\~\^" ,(write-to-string sep) "\~\}")) l))

但是尝试时:

(join #\Tab '("a" "b" "c"))

当然不希望得到此结果:"a#\\Tabb#\\Tabc",因为

This results of course is sth not desired: "a#\\Tabb#\\Tabc", since

(macroexpand-1 '(join #\Tab '("a" "b" "c")))
;; results in:
(FORMAT NIL "~{~A~^#\\Tab~}" L)
;; instead of:
(FORMAT NIL "~{~A~^#\Tab~}" L)

但是我看不到如何实现所需宏的这一步... 有人对此有启发吗?

But I don't see how to achieve this step to the desired macro ... Has anybody an enlightening about this?

关于元编程问题的元编程的种类...

Kind of a metaprogramming on metaprogramming problem ...

好吧,现在我知道@Rainer Joswig已经发布在 在列表中加入字符串的规范方法是什么? /a>

Okay, now I see, that @Rainer Joswig has already posted in What's the canonical way to join strings in a list?

此问题的解决方案.但是,如果有一种方法可以将"#\\Tab"表示为"#\Tab",则可以得出一个更紧凑的定义. 但是以某种方式,Lisp阅读器似乎总是以字符串形式将"\Tab"识别为一个字母.可以编写一个函数来做到这一点吗?

a solution to this problem. However, if there would be a way, to represent "#\\Tab" as "#\Tab", one could come to a more compact definition. But somehow the Lisp reader seems in a string always to recognize "\Tab" as one letter. Is it possible to write a function to do that?

备注

在R中,特别是对于元编程,存在诸如as.name("myvar")之类的函数,这些函数从字符串"myvar"中生成符号myvar. 和类似deparse(substitute(x))的表达式,它使用符号x并从中创建文字字符串"x". Deparse后退print()命令的执行,从而转义特殊符号. deparse(deparse(substitute(x)))例如生成"\"x\""-尽管围绕此表达式的parse(text = ... )会再次使"x"成为parse(text = deparse(deparse(substitute(x)))). 在common-lisp中如何实现这样的事情? 例如(a-special-function #\Tab)导致(文字):"#\Tab"作为字符串?

In R, there exist especially for metaprogramming, functions like as.name("myvar") which generate the symbolmyvar out of the string "myvar". and expressions like deparse(substitute(x)) which takes the symbol x and creates out of it a literal string "x". Deparse steps back the execution of print() commands, whereby escaping special symbols. deparse(deparse(substitute(x))) would e.g. generate "\"x\"" - While parse(text = ... ) around this expression would make out of it "x" again parse(text = deparse(deparse(substitute(x)))). How such things could be achived in common-lisp? e.g.(a-special-function #\Tab) resulting in (literal): "#\Tab" as a string?

结语

谢谢@Sylwester !!他没有宏就解决了它.而且非常优雅!

Thank you @Sylwester!! He solved it without macro. And very elegantly!

推荐答案

您的问题是您尝试将#\Tab添加到格式中,但这就是使用文字的方式.如果您只是在格式字符串中插入了制表符或包含它的字符串,它将执行您想要的操作:

Your problem is that you try to add #\Tab to the format, but that is just how you do it with literals. If you just inserted a tab character or a string consisting of it in the format string it will do what you want:

(defun join (l &key (sep ", "))
  (format nil (format nil "~a~a~a" "~{~a~^" sep "~}") l))

(join '(1 2 3)) 
; ==> "1, 2, 3"
(join '(1 2 3) :sep #\Tab) 
; ==> "1    2   3"

这篇关于common-lisp中更好的pythonic`join`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆