在OCaml的列表中打印元素

时间:2018-09-27 01:11:49

标签: printf ocaml

我想编写一个尾部递归函数,以像这样在单独的行中打印字符串列表中的元素:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.sendNotification = functions.firestore.document("Users/{user_id}/Notifications/{notification_id}").onWrite((event) => {

    const user_id = event.params.user_id;
    const notification_id = event.params.notification_id;

    return admin.firestore().collection("Users").doc(user_id).collection("Notifications").doc(notification_id).get()
    .then(queryResult => {
        const {from:from_user_id, message:from_message} = queryResult.data();

        const from_data = admin.firestore().collection("").doc(from_user_id).get();
        const to_data = admin.firestore().collection("Users").doc(user_id).get();

        return Promise.all([from_data, to_data, from_message]); // added from_message so it's available in the next .then
    })
    .then(([from_data, to_data, from_message]) => { // added from_message
        const from_name = from_data.data().name;
        const {name:to_name, token_id} = to_data.data();

        console.log("From: " + from_name + " | To : " + to_name);

        const payload = {
            notification : {
                title : "Notification From : " + from_name,
                body : from_message,
                icon : 'default'
            }
        };

        return admin.messaging().sendToDevice(token_id, payload);
    })
    .then(result => {
        return console.log("Notification Sent");
    });
});

我可以使用print_endline使其正常工作:

  # printlist ["a";"b";"c"];;
   a
   b
   c
   - : unit = ()
   # printlist ["hello";"thanks"];;
   hello
   thanks
   - : unit = ()

但是,一旦我切换到printf,它就不再起作用了。我的printf版本有什么问题?

let rec printlist strlist =
  match strlist with 
  | [] ->  print_endline "" 
  | hd::[] ->  print_endline hd
  | hd :: tl -> print_endline hd  ; printlist tl;;

2 个答案:

答案 0 :(得分:2)

从本质上讲,您正在尝试使用printf,而不使用格式。 printf的第一个参数必须是一个常量字符串。所以你应该有这个:

printf "%s" hd

而不是这个:

printf hd

要了解为什么需要这样做,请想象一下,如果输入中的某些字符串包含百分比字符,会发生什么情况。事情很快就会失控(按类型)。

答案 1 :(得分:1)

除了杰弗里的答案,我建议您更多地使用标准库,以便编写更简洁的代码。

例如,

List.iter在列表的所有元素上调用给定函数:

let print_list l = List.iter (fun e -> Printf.printf "%s\n" e) l

巧妙地使用partial application,可以使此行更短,更易读:

let print_list = List.iter (Printf.printf "%s\n")

与函数唯一的区别是最后一个元素之后的换行符。


另一方面,与其一遍又一遍地打印元素,不如使用一种更为实用且惯用的方法,那就是先构建整个字符串,然后再进行打印。

幸运的是,标准库可以满足您的要求。 String.concatstring list中的元素连接成一个大字符串。您还可以指定一个用作分隔符的字符串,而不必担心最后一个元素之后的换行符。

let print_list l = print_string (String.concat "\n" l)