神奇的sprintf函数-如何包装? [英] Magic sprintf function - how to wrap it?

查看:102
本文介绍了神奇的sprintf函数-如何包装?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试包装对sprintf函数的调用.这是我的尝试:

I am trying to wrap a call to sprintf function. Here's my attempt:

let p format args = "That was: " + (sprintf format args)

let a = "a"
let b = "b"

let z1 = p "A %s has invalid b" a 

这似乎可行,输出为

val p : format:Printf.StringFormat<('a -> string)> -> args:'a -> string
val a : string = "a"
val b : string = "b"
val z1 : string = "That was: A a has invalid b"

但是它不能用于多个arg:

But it wouldn't work with more than one arg:

let z2 = p "A %s has invalid b %A" a b

我收到编译时错误:

let z2 = p "A %s has invalid b %A" a b;;
---------^^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(7,10): error FS0003: This value is not a function and cannot be applied

我如何创建一个可以与任意数量的args一起使用的函数?

How can I create a single function which would work with any number of args?

UPD . Tomas建议使用

UPD. Tomas has suggested to use

let p format = Printf.kprintf (fun s -> "This was: " + s) format

它确实有效.这是一个例子

It works indeed. Here's an example

let p format = Printf.kprintf (fun s -> "This was: " + s) format

let a = p "something like %d" 123
// val p : format:Printf.StringFormat<'a,string> -> 'a
// val a : string = "This was: something like 123"

但是问题是我的功能的主要目的是做一些除格式化工作之外的工作,因此我尝试使用建议的代码,如下所示

But the thing is that main purpose of my function is to do some work except for formatring, so I tried to use the suggested code as follows

let q format = 
    let z = p format // p is defined as suggested
    printf z // Some work with formatted string

let z = q "something like %d" 123

它不再起作用:

  let z = q "something like %d" 123;;
  ----------^^^^^^^^^^^^^^^^^^^

stdin(30,15): error FS0001: The type ''c -> string' is not compatible with the type 'Printf.TextWriterFormat<('a -> 'b)>'

我该如何解决?

推荐答案

为此,您需要使用currying-函数p需要采用format并返回由printf函数(然后可以是带有一个或多个参数的函数).

For this to work, you need to use currying - your function p needs to take the format and return a function returned by one of the printf functions (which can then be a function taking one or more arguments).

这不能使用sprintf来完成(因为您必须显式传播参数.但是,您可以使用kprintf,它将 continuation 作为第一个参数::

This cannot be done using sprintf (because then you would have to propagate the arguments explicitly. However, you can use kprintf which takes a continuation as the first argument::

let p format = Printf.kprintf (fun s -> "This was: " + s) format

以格式化的字符串调用延续,因此您可以在返回之前对结果字符串进行任何所需的操作.

The continuation is called with the formatted string and so you can do whatever you need with the resulting string before returning.

编辑:要回答您的扩展问题,诀窍是将所有其他工作放到续篇中:

To answer your extended question, the trick is to put all the additional work into the continuation:

let q format = 
  let cont z =
    // Some work with formatted string
    printf "%s" z 
  Printf.kprintf cont format 

这篇关于神奇的sprintf函数-如何包装?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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