In part 2 of this series, we break down how professionals can leverage ChatGPT to code. This blog breaks down how to do that with both the free and paid version.
Overview
If you read part 1, you’ll know it was often possible to make 3.5 perform close to the level of 4. Fair warning before we get started, this is not possible for some of the more helpful aspects of using ChatGPT-4 for code. I’ll indicate a few uses for 3.5, but when we move into 4, I’ll illustrate why the investment is well worth it, and how 3.5 falls short.
Levering ChatGPT-3.5 for code
Boilerplate
ChatGPT-3.5 excels at outputting mundane but custom code. For example, a Vue template, but with several complications already integrated:
Prompt: Output a Vue template for a NoteCard component. Control if it appears through the computed that checks both a shouldAppear prop, and that it has a Title and Description that isn’t null. It should optionally take a link, which won’t appear if there is no link destination, and says “Link” if no link text is supplied. Provide a mock API call in mounted that checks an endpoint to see if that endpoint has data. While the API call is in progress, loading must be set to true, and different styles applied while loading is true.
I’ll highlight what it does well and wrong below, you can check out the full code response at the end:
<template>
<div class=”note-card” v-if=”shouldAppear && (title || description)”>
<div class=”note-card-content”>
<h3>{{ title }}</h3>
<p>{{ description }}</p>
<a v-if=”linkDestination” :href=”linkDestination”>{{ linkText || ‘Link’ }}</a>
</div>
<div class=”note-card-loader” v-if=”loading”>
<!– Loading styles go here –>
Loading…
</div>
</div>
</template>
<script>
export default {
props: {
…
},
data() {
…
},
computed: {
// Computed property to check if the card should appear
isVisible() {
return this.shouldAppear && (this.title || this.description);
},
},
mounted() {
if (this.linkDestination) {
// Simulate an API call
this.loading = true;
…
}, 2000); // Simulate a 2-second API call
}
},
};
</script>
<style scoped>
…
</style>
The good:
It included everything I said
It auto-simulates a time-delay on the API call, so I could test how loading feels without needing to hook up the API
The bad:
It did not interpret my “loading means different styles” correctly
It doesn’t use the computed property “isVisible”, even though it has duplicate logic
I didn’t ask for styles besides maybe hinting at a placeholder for loading styles
A few Vue good practice violations
ChatGPT-4 did all of those things correctly with the first prompt, of course.
But a fix is easy. I prompted it:
Use the computed property, don’t duplicate the code. Don’t give me styles, just a placeholder for loading. Also, I want to change styles when loading is true, not have different DOM elements. Follow good Vue coding practices.
This rectified all of the major mistakes and made it nearly identical to ChatGPT-4’s output.
Questions
Method Help
For the most part, I’ve entirely quit endlessly searching documentation and who knows what else, as ChatGPT can tell me right away. For example:
Prompt: I’m using indexOf(‘six’) in Javascript to try and find where the word ‘six’ is in a string, but I want the last occurance, not the first.
ChatGPT-3.5:
The indexOf method in JavaScript only returns the index of the first occurrence of the specified substring within the given string. If you want to find the index of the last occurrence of ‘six’ in a string, you can use the following approach:
var str = “This is the first six. There is another six here. And the last six is here.”; var lastIndex = str.lastIndexOf(“six”); console.log(“Last occurrence of ‘six’ is at index: ” + lastIndex);
In this example, we use the lastIndexOf method instead of indexOf. It will search for the last occurrence of “six” in the string and return its index. The result will be the index of the last occurrence of “six” in the string.
I always recommend reading documentation when it comes to security, and in general I would suggest looking at documentation. However, small language nuances like the above example, and other mundane features are much more easily researched with ChatGPT.
Explain This Code
How obvious is it what this code is doing, right off the bat?
let options = props.options.map((locationNamePair, index) => {
return (
<Link href={locationNamePair[0]} key={index + locationNamePair[0]}>
<a className={styles.optionsLink}>{locationNamePair[1]}</a>
</Link>
);
});
let mobileStructureOnClick = (
<div className={styles.mobileLinks}>
{options}
</div>
)
The code names, and the filename being OptionsAccordion may help, but especially for a new React developer, some of the constructions and variable usage may be confusion. ChatGPT responds to “Can you explain this code to me?”
ChatGPT-3.5:
Certainly! This code appears to be part of a React component and is used to generate a list of links based on the props.options array. Let me break it down step by step:
let options = props.options.map((locationNamePair, index) => { … });Here, you are mapping over the props.options array. It looks like props.options is an array of pairs, where each pair consists of a URL (locationNamePair[0]) and a display name (locationNamePair[1]). The .map() function is used to iterate over each pair in the array.Inside the .map() function, for each pair, a JSX element is created using the <Link> and <a> tags. The href attribute of the <Link> component is set to the URL (locationNamePair[0]), and the key attribute is set to the index plus locationNamePair[0] to uniquely identify each link element. The content of the link (<a>) is set to the display name (locationNamePair[1]), and it has a class name styles.optionsLink, which is likely used for styling purposes.
let mobileStructureOnClick = ( <div className={styles.mobileLinks}> {options} </div> );Here, you are creating a JSX element mobileStructureOnClick. This element contains a <div> with the class name styles.mobileLinks, which is also likely used for styling. Inside this <div>, you are rendering the options variable.In other words, you are rendering the list of links generated earlier inside this <div>, and it will be displayed as a list of clickable options on your webpage.
Overall, this code dynamically generates a list of links based on the data in props.options and renders them inside a <div>, which is styled for mobile view. It’s a common pattern in React for rendering dynamic lists of elements based on data.
Summary
ChatGPT-3.5 is great for boilerplate, code explanations, syntax lookup, and even some mundane code editing.
Leveraging ChatGPT-4
ChatGPT-4 is senior developer who has not slept in several days. He will output quality code, knows the ins and outs of a language or system, and can provide high level feedback. You’ll want to fact check him though, maybe that lack of sleep caused him to mix some stuff up.
A quick demonstration of ChatGPT-4’s superiority, and proof of higher levels of knowledge:
Me:
I’m making a header component in react with Typescript, which will take dynamic numbers of JSX children. I need it to map over them and wrap them each in a button. The buttons will control whether or not panels show up below. Assume state is managed above the header, and the header just has access to an index setting it can call with the button clicks. Output just the component.
ChatGPT-3.5:
import React, { useState } from ‘react’;
interface HeaderProps {
children: React.ReactNode[];
}
const Header: React.FC<HeaderProps> = ({ children }) => {
const [activeIndex, setActiveIndex] = useState<number | null>(null);
const handleButtonClick = (index: number) => {
setActiveIndex(activeIndex === index ? null : index);
};
return (
<div>
{React.Children.map(children, (child, index) => (
<div key={index}>
<button onClick={() => handleButtonClick(index)}>Toggle Panel {index + 1}</button>
{activeIndex === index && child}
</div>
))}
</div>
);
};
export default Header;
Fails:
Controls index in header, I said that was done in parent
I said a button wraps the child, this puts a div…and doesn’t wrap the child at all with the button
key={index} — The instructions said this was a dynamic list, so just using index here is inaccurate
this check: activeIndex === index && child is redundant
Not only does this get some key react features wrong, it would fail to work visually given the structure it decided on.
ChatGPT-4 (with React Expert):
import React, { ReactNode } from ‘react’;
interface HeaderProps {
children: ReactNode[];
onButtonClick: (index: number) => void;
}
const Header: React.FC<HeaderProps> = ({ children, onButtonClick }) => {
return (
<div>
{children.map((child, index) => (
<button key={index} onClick={() => onButtonClick(index)}>
{child}
</button>
))}
</div>
);
};
export default Header;
Fails: Same key mistake
ChatGPT-4, utilizing a publicly accessible GPT, manages to create almost exactly what I described, wrapping each child in a button, and outputting each button into a div, which presumably I could style to be the header container.
GPTs
The GPT store is ChatGPT-4’s other massive advantage over ChatGPT-3.5. GPTs allow you to pre-load custom prompts that drive the rest of the interaction, as well as custom data and API calls. For example, let’s design one that will not make that key mistake.
Custom Instructions
Do you have a set of standards you like to enforce on your code? With ChatGPT-3.5, you’ll have to paste these steps in each new chat, and in a chat where you exceed the context window (You’ve had too many back-and-forths and it doesn’t remember the first message anymore), it will also forget. ChatGPT-4 does not have this problem. A simplistic example:
Me:
I want all of my variables to be prefixed with “mxf_”. Anything I give you in this converstion, prefix it with “mxf_”. Here’s the first code:
ChatGPT-3.5:
Sure, here’s your code with the variables prefixed with “mxf_”:
let mxf_userName = ‘John Doe’;
const mxf_userId = 102;
var mxf_userStatus = ‘active’;
console.log(‘User Name:’, mxf_userName);
console.log(‘User ID:’, mxf_userId);
console.log(‘User Status:’, mxf_userStatus);
mxf_userName = ‘Jane Doe’;
mxf_userStatus = ‘inactive’;
console.log(‘Updated User Name:’, mxf_userName);
console.log(‘Updated User Status:’, mxf_userStatus);
Now all variables are prefixed with “mxf_”.
Now here is that same code after sending it many, many messages:
ChatGPT-3.5:
The provided code is written in JavaScript and defines variables userName, userId, and userStatus. It then logs their values to the console and updates the values of userName and userStatus before logging the updated values.
Here’s a breakdown of the code: …
As you can see, it has forgotten the initial instruction. This problem doesn’t exist with ChatGPT-4’s GPTs. A simple instruction like this would be remembered for the whole chat:
But, it gets better. Perhaps you have many different things you’d like to do, and perhaps they conflict with each other, or would result in a list of such dizzying length you would struggle to know what you’ve put in it. Or, maybe you’re working within a context of code you’ve already submitted — If you update a GPT, any existing chat with that GPT does not receive the update. How then, could one get their updated GPT to see their context without remaking the whole chat?
Well with ChatGPT-4, you can simply reference GPTs from within the chat! My bot, for example, could be called upon to clean up the code that default ChatGPT-4 creates:
Above, I select the bot, Code Standard Bot. In the chat below, notice how it changes from ChatGPT to Code Standard Bot, and it implements the simplistic “mxf_” prefix I’d declared earlier.
This is so cool — imagine all the different ‘stored procedures’, if you will, that could exist across many different GPTs. All you have to do is summon them up in a single chat, forging code from idea to perfected reality.
Data Relevance and Internet
ChatGPT-4 is also internet connected and trained on more recent data. This means ChatGPT-4 better intuits responses from more recent data, and also Bing searches questions with obvious temporal aspects. For example:
Leave A Comment