我试图创建一个模仿" adda"汽车和司机的行为,我可以传递任何一串'和' s。我们的想法是返回一个函数,然后在后面的列表中执行该函数。对此函数的调用可能如下所示:
((cxr" dd")'(1 2 3))
我已逐步建立到我认为它应该工作的位置,首先创建一个letrec,返回正确的car和cdr字符串。然后将letrec的主体移动到定义内的lambda主体。
(define (cxr cmdString) ;named function to call
(lambda (X) ;beginning of un-named function to return
(
(cond
;if the string passed in is empty, return the arguments to the second function
((= 0 (string-length cmdString)) 'X)
;if its an 'a', add a call to car to the list and call the function again with a shorter command string.
((char=? #\a (string-ref cmdString 0)) (list (quote car) (cxr (substring cmdString 1 (string-length cmdString)))))
;if its a 'd', add a call to cdr to the list and call the function again with a shorter command string.
((char=? #\d (string-ref cmdString 0)) (list (quote cdr) (cxr (substring cmdString 1 (string-length cmdString)))))
)
)
)
)
((cxr "a") '(1 2 3)) ;call the function
使用Repl.it,我收到一条对我来说毫无意义的错误消息。为了让它以不同的方式工作,我已经做了一点点,但我想知道我做错了什么。
我建立的Letrec,返回正确的汽车字符串和cdr:
(letrec
(
(cxr
(lambda (cmdString)
(cond
((= 0 (string-length cmdString)) 'X)
((char=? #\a (string-ref cmdString 0)) (list (quote car) (cxr (substring cmdString 1 (string-length cmdString)))))
((char=? #\d (string-ref cmdString 0)) (list (quote cdr) (cxr (substring cmdString 1 (string-length cmdString)))))
)
)
)
)
(cxr "daa") ;can change "daa" to any combination of 'd's and 'a's.
)
具有我寻求的行为的Finagled版本,没有经过良好测试(并且有点丑陋):
(define (cxr X)
(list 'lambda '(X)
(letrec
(
(computecxr
(lambda (cmdString)
(cond
((= 0 (string-length cmdString)) 'X)
((char=? #\a (string-ref cmdString 0)) (list 'car (computecxr (substring cmdString 1 (string-length cmdString)))))
((char=? #\d (string-ref cmdString 0)) (list 'cdr (computecxr (substring cmdString 1 (string-length cmdString)))))
)
)
)
)
(computecxr X)
)
)
)
(print (cxr "a"))
((eval (cxr "dd")) '(1 2 3))
任何建议都会有所帮助。谢谢。
编辑:亚历克西斯,我没有看到我的问题和另一个问题之间的相关性。我在我的程序中没有使用if,也不是我得到的错误。你能解释为什么你认为它是重复的吗?答案 0 :(得分:1)
在您的代码中,由于错误使用括号而导致语法错误的一部分,您正在尝试使用quote
和list
构建列表,然后必须评估< / em>得到结果。
但是如果你想探索函数式编程,你应该避免根据具体的数据结构来考虑函数,比如列表。相反,您应该开始将它们视为语言的 values ,就像整数和字符串一样,例如作为其他函数返回的函数,或者应用于其他表达式的表达式,因为它们评估为功能
以下是您的问题的可能解决方案,编写为高级函数,使用DrRacket进行测试:
(define (cxr cmd-string)
(if (= 0 (string-length cmd-string))
(lambda (x) x)
(let* ((first-char (string-ref cmd-string 0))
(f (if (char=? first-char #\a) car cdr)))
(lambda (x) (f ((cxr (substring cmd-string 1 (string-length cmd-string))) x))))))
((cxr "add") '(1 2 3)) ; => 3
第一个测试检查字符串是否为空,在这种情况下返回标识函数(即返回其参数的函数)。
否则,字符串的第一个字符绑定到first-char
,然后相应的函数绑定到f
(注意car
和cdr
是两个原语函数),最后返回的值是一个新函数,带有一个参数x
,它将f
应用于x
函数的结果,该函数是cxr
递归调用(define (mk-cxr cmd-string)
(define (mk-body string)
(if (= 0 (string-length string))
'(x)
(let* ((first-char (string-ref string 0))
(operation (if (char=? first-char #\a) 'car 'cdr)))
(list (cons operation (mk-body (substring string 1 (string-length string))))))))
(cons 'lambda (cons '(x) (mk-body cmd-string))))
(mk-cxr "add") ; => (lambda (x) (car (cdr (cdr x))))
的结果1}}。
加
要查看函数方法和“build-a-list-represent-a-function”之间的区别,特别是递归的不同用法,请将上述函数与以下函数进行比较:
SSL
答案 1 :(得分:1)
原始访问器不会神奇地生成,但通常是作为组合的全局绑定。
但是可以这样做。一个名为public class InstantRequestHandler {
public String sendGetRequest(String uri) {
try {
URL url = new URL(uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String result;
StringBuilder sb = new StringBuilder();
while((result = bufferedReader.readLine())!=null){
sb.append(result);
}
return sb.toString();
} catch (Exception e) {
return null;
}
}
public String sendPostRequest(String requestURL,
HashMap<String, String> postDataParams) {
URL url;
String response = "";
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
response = br.readLine();
} else {
response = "Error Registering";
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Map.Entry<String, String> entry : params.entrySet()) {
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
}
的常见程序通常是将程序链接在一起的东西,这就是这里发生的事情。通过撰写,compose
并且不使用cxr
非常简单。编译器几乎没有机会优化使用eval
的代码,并且如果以某种方式证明代码具有来自用户输入的元素,则存在安全问题。
eval
答案 2 :(得分:1)
确定。让我们在您的问题中进行第一次尝试,并使用适当的缩进和正常的)
展示位置进行清理:
(define (cxr cmdString) ; named function to call
(lambda (X) ; beginning of un-named function to return
((cond
; if the string passed in is empty, return the arguments to the second function
[(= 0 (string-length cmdString)) 'X]
; if its an 'a', add a call to car to the list and call the function again with a shorter command string.
[(char=? #\a (string-ref cmdString 0))
(list (quote car) (cxr (substring cmdString 1 (string-length cmdString))))]
; if its a 'd', add a call to cdr to the list and call the function again with a shorter command string.
[(char=? #\d (string-ref cmdString 0))
(list (quote cdr) (cxr (substring cmdString 1 (string-length cmdString))))]))))
((cxr "a") '(1 2 3)) ; call the function
现在可以稍微轻松地看到问题了。第一个问题是一个简单的paren错误,你将lambda的主体包裹在一组不应该存在的括号中。请记住,在方案中,括号通常表示函数调用。这就是您收到application: not a procedure
错误的原因。现在已修复:
(define (cxr cmdString) ; named function to call
(lambda (X) ; beginning of un-named function to return
(cond
; if the string passed in is empty, return the arguments to the second function
[(= 0 (string-length cmdString)) 'X]
; if its an 'a', add a call to car to the list and call the function again with a shorter command string.
[(char=? #\a (string-ref cmdString 0))
(list (quote car) (cxr (substring cmdString 1 (string-length cmdString))))]
; if its a 'd', add a call to cdr to the list and call the function again with a shorter command string.
[(char=? #\d (string-ref cmdString 0))
(list (quote cdr) (cxr (substring cmdString 1 (string-length cmdString))))])))
((cxr "a") '(1 2 3)) ; call the function
代码给出了结果:
'(car #<procedure>)
它返回一个包含两个元素的列表,相当于(list 'car #<procedure>)
。这可能不是你的意思。我猜你想让它返回列表car
的{{1}},即'(1 2 3)
。首先,在评论中写下:
1
现在我们已经记录了;; cxr : CmdString -> (ConsTree -> Any)
;; Given a command string containing 'a' and 'd' characters, returns
;; a function that gets the corrosponding element in the cons tree.
;; For example, (cxr "a") should return a function equivalent to car,
;; (cxr "d") should return a function equivalent to cdr, and
;; (cxr "add") should return a function equivalent to caddr.
返回的内容,我们可以用它做点什么。我们可以在递归的情况下正确使用它。它返回一个接受cons树的函数,因此我们可以将它应用于(cxr ...)
,这是我们的cons树:X
。这将返回((cxr ...) X)
的子句,该子句对应于字符串的其余部分,X
情况为(cddr X)
。因此,您只需将"add"
或car
应用于:
cdr
在上下文中:
; 'a' case
(car ((cxr ...) X))
; 'd' case
(cdr ((cxr ...) X))
现在这给出了这个错误:
(define (cxr cmdString) ; named function to call
(lambda (X) ; beginning of un-named function to return
(cond
; if the string passed in is empty, return the arguments to the second function
[(= 0 (string-length cmdString)) 'X]
; if its an 'a', call car on a recursive call using the rest of the command string.
[(char=? #\a (string-ref cmdString 0))
(car ((cxr (substring cmdString 1 (string-length cmdString))) X))]
; if its a 'd', call cdr on a recursive call using the rest of the command string.
[(char=? #\d (string-ref cmdString 0))
(cdr ((cxr (substring cmdString 1 (string-length cmdString))) X))])))
((cxr "a") '(1 2 3)) ; call the function
car: contract violation
expected: pair?
given: 'X
来自哪里?基本情况。我们也需要修复基本情况,但这很简单,只需使用'X
代替X
:
'X
测试它:
;; cxr : CmdString -> (ConsTree -> Any)
;; Given a command string containing "a" and "d" characters, returns
;; a function that gets the corrosponding element in the cons tree.
;; For example, (cxr "a") should return a function equivalent to car,
;; (cxr "d") should return a function equivalent to cdr, and
;; (cxr "add") should return a function equivalent to caddr.
(define (cxr cmdString) ; named function to call
(lambda (X) ; beginning of un-named function to return
(cond
; if the string passed in is empty, return the argument to the second function
[(= 0 (string-length cmdString)) X]
; if its an 'a', call car on a recursive call using the rest of the command string.
[(char=? #\a (string-ref cmdString 0))
(car ((cxr (substring cmdString 1 (string-length cmdString))) X))]
; if its a 'd', call cdr on a recursive call using the rest of the command string.
[(char=? #\d (string-ref cmdString 0))
(cdr ((cxr (substring cmdString 1 (string-length cmdString))) X))])))
本着@Sylwester > ((cxr "a") '(1 2 3))
1
> ((cxr "d") '(1 2 3))
'(2 3)
> ((cxr "add") '(1 2 3))
3
> ((cxr "adda") '((1 2 3) 4))
3
答案的精神,您可以将此代码翻译为使用compose
而不是compose
,同时保留原始版本的一些相同结构代码:
(lambda (X) ...)
如果你看一下这个结构,这与你原来写的不太一样。它没有lambda,因为它使用;; cxr : CmdString -> (ConsTree -> Any)
;; Given a command string containing "a" and "d" characters, returns
;; a function that gets the corrosponding element in the cons tree.
;; For example, (cxr "a") should return a function equivalent to car,
;; (cxr "d") should return a function equivalent to cdr, and
;; (cxr "add") should return a function equivalent to caddr.
(define (cxr cmdString)
(cond
; if the string passed in is empty, return the identity function.
[(= 0 (string-length cmdString)) identity]
; if its an 'a', compose car with a recursive call using the rest of the command string.
[(char=? #\a (string-ref cmdString 0))
(compose car (cxr (substring cmdString 1 (string-length cmdString))))]
; if its a 'd', compose cdr with a recursive call using the rest of the command string.
[(char=? #\d (string-ref cmdString 0))
(compose cdr (cxr (substring cmdString 1 (string-length cmdString))))]))
构建函数,它返回基本案例的标识函数而不是符号compose
,并且对于它使用的递归情况{{ 1}}您使用'X
和compose
。