ChatGPT 创作代码能力处于什么水平?有可能用于软件的实际开发和维护吗?

很难一句话概括,如果只说『可能用于开发和维护』的话,答案是肯定的。但也有坑,下面有具体的例子。

我前段时间用ChatGPT搜过若干种不同语言的代码例子,总体感受:

搜索引擎一般能回答一句话之内的问题,ChatGPT能理解明显更加复杂的问题描述并给出完整的程序ChatGPT写出的程序大体上逻辑正确,但不能100%排除语法或逻辑错误ChatGPT写出的程序,不容易用Google找到一模一样的代码。更像是它在一定程度上理解了问题以后,用自己对该语言的了解来组合出的回答。打个比方,用中文提问中文语料库里明显没有的问题,ChatGPT提供的中文回答更像是从其他语种的语料库里找出来再翻译过来的语法相似的语言,ChatGPT可能会给出张冠李戴的回答

例1:ChatGPT用Scala实现并查集

class UnionFind(size: Int) { private val parent = Array.tabulate(size)(identity) private val rank = Array.fill(size)(0) def find(x: Int): Int = { if (parent(x) != x) { parent(x) = find(parent(x)) } parent(x) } def union(x: Int, y: Int): Unit = { val rootX = find(x) val rootY = find(y) if (rootX != rootY) { if (rank(rootX) < rank(rootY)) { parent(rootX) = rootY } else if (rank(rootX) > rank(rootY)) { parent(rootY) = rootX } else { parent(rootY) = rootX rank(rootX) += 1 } } } def connected(x: Int, y: Int): Boolean = find(x) == find(y) }

我Google到两份相对比较类似的Scala代码(1, 2),但差异都很明显。我觉得可以说这是ChatGPT根据自身对并查集和对Scala的理解,『创造』出来的代码。

例2: 我在用F#做AoC 22第23天问题的时候,需要把输入文本中出现 “#” 的行与列位置记录下来。我的提问:

how to parse lines of strings and collect all the X and Y locations of “#” characters into a set of int tuple?

ChatGPT给出的F#代码:(我问题中并没有提到F#,ChatGPT是根据上下文判断的)

open Microsoft.FSharp.Collections let lines = [ “#####”; “##.#”; “#####” ] let set = lines |> Seq.mapi (fun y line -> line |> String.toCharArray |> Array.mapi (fun x c -> (x, y))) |> Seq.concat |> Seq.filter (fun (x, y) -> fst (x, y) = #) |> Set.ofSeq

这段代码大体正确,但有个错: Array.mapi (fun x c -> (x, y)) 没有记录字符c ,应该写成fun x c -> (c, (x, y)) ,这样能够正确对应下面的filter语句。另外有两处比较繁琐:一是String.toCharArray | Array.mapi没有必要,F#的string本身就是sequence,可以用Seq.mapi。二是filter后面既然已经做了destructuring,再用fst (x, y)是多此一举。

显然,上面的代码可以说是『原创』而不是从现成代码copy过来的,连bug也一并创造了。

例3:我在提问Idris的Lens问题的时候,ChatGPT看起来把Haskell的Lens库张冠李戴了。也许是因为这两种语言看上去很像?

例4: 我通过一系列提问,让ChatGPT写出了完整的AoC 22第5天问题的解答,其中有两处出入栈顺序搞反了。可以搜到其他更复杂的例子,包括生成新语言的词法和语法分析器。

总的来说,ChatGPT生成的代码已经具有一定实用性和创造性,能够用来替代一部分初级的开发工作。它的代码质量,可能还高过不少初/中级工程师的水平。相比搜索引擎,它还能理解和保持更复杂的上下文,你可以引导它一步一步生成更大规模的代码。

但它生成的代码并不是100%无错,你还是得小心中间的bug。也许让它同时生成单元测试是个不错的办法。

Leave a Reply